authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-18 20:20:46-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-05-18 20:20:46-04:00
log6435750c99e705eb40bbdf75e51a3493d683e951
tree2f1ab1dc537ba8804ae6d1e0bdd094d646625e53
parentd228d86059cf16f4b37b2853cc1323bf98d242cf
parent667236668f865de4c854a047d65017140317e7e9
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #8554 from ziglang/stage2-whole-file-astgen

Stage2 whole file astgen

508 files changed, 40200 insertions(+), 32931 deletions(-)

CMakeLists.txt+1-2
...@@ -550,7 +550,6 @@ set(ZIG_STAGE2_SOURCES...@@ -550,7 +550,6 @@ set(ZIG_STAGE2_SOURCES
550 "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig"550 "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig"
551 "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig"551 "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig"
552 "${CMAKE_SOURCE_DIR}/src/codegen/riscv64.zig"552 "${CMAKE_SOURCE_DIR}/src/codegen/riscv64.zig"
553 "${CMAKE_SOURCE_DIR}/src/codegen/spu-mk2.zig"
554 "${CMAKE_SOURCE_DIR}/src/codegen/wasm.zig"553 "${CMAKE_SOURCE_DIR}/src/codegen/wasm.zig"
555 "${CMAKE_SOURCE_DIR}/src/codegen/x86_64.zig"554 "${CMAKE_SOURCE_DIR}/src/codegen/x86_64.zig"
556 "${CMAKE_SOURCE_DIR}/src/glibc.zig"555 "${CMAKE_SOURCE_DIR}/src/glibc.zig"
...@@ -595,7 +594,7 @@ set(ZIG_STAGE2_SOURCES...@@ -595,7 +594,7 @@ set(ZIG_STAGE2_SOURCES
595 "${CMAKE_SOURCE_DIR}/src/type.zig"594 "${CMAKE_SOURCE_DIR}/src/type.zig"
596 "${CMAKE_SOURCE_DIR}/src/value.zig"595 "${CMAKE_SOURCE_DIR}/src/value.zig"
597 "${CMAKE_SOURCE_DIR}/src/windows_sdk.zig"596 "${CMAKE_SOURCE_DIR}/src/windows_sdk.zig"
598 "${CMAKE_SOURCE_DIR}/src/zir.zig"597 "${CMAKE_SOURCE_DIR}/src/Zir.zig"
599 "${CMAKE_SOURCE_DIR}/src/Sema.zig"598 "${CMAKE_SOURCE_DIR}/src/Sema.zig"
600)599)
601600
build.zig+28-15
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const builtin = @import("builtin");
2const std = @import("std");1const std = @import("std");
2const builtin = std.builtin;
3const Builder = std.build.Builder;3const Builder = std.build.Builder;
4const tests = @import("test/tests.zig");4const tests = @import("test/tests.zig");
5const BufMap = std.BufMap;5const BufMap = std.BufMap;
...@@ -54,6 +54,7 @@ pub fn build(b: *Builder) !void {...@@ -54,6 +54,7 @@ pub fn build(b: *Builder) !void {
54 const skip_compile_errors = b.option(bool, "skip-compile-errors", "Main test suite skips compile error tests") orelse false;54 const skip_compile_errors = b.option(bool, "skip-compile-errors", "Main test suite skips compile error tests") orelse false;
55 const skip_run_translated_c = b.option(bool, "skip-run-translated-c", "Main test suite skips run-translated-c tests") orelse false;55 const skip_run_translated_c = b.option(bool, "skip-run-translated-c", "Main test suite skips run-translated-c tests") orelse false;
56 const skip_stage2_tests = b.option(bool, "skip-stage2-tests", "Main test suite skips self-hosted compiler tests") orelse false;56 const skip_stage2_tests = b.option(bool, "skip-stage2-tests", "Main test suite skips self-hosted compiler tests") orelse false;
57 const skip_install_lib_files = b.option(bool, "skip-install-lib-files", "Do not copy lib/ files to installation prefix") orelse false;
5758
58 const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false;59 const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false;
59 const is_stage1 = b.option(bool, "stage1", "Build the stage1 compiler, put stage2 behind a feature flag") orelse false;60 const is_stage1 = b.option(bool, "stage1", "Build the stage1 compiler, put stage2 behind a feature flag") orelse false;
...@@ -62,19 +63,23 @@ pub fn build(b: *Builder) !void {...@@ -62,19 +63,23 @@ pub fn build(b: *Builder) !void {
62 const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse (is_stage1 or static_llvm);63 const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse (is_stage1 or static_llvm);
63 const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h");64 const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h");
6465
65 b.installDirectory(InstallDirectoryOptions{66 if (!skip_install_lib_files) {
66 .source_dir = "lib",67 b.installDirectory(InstallDirectoryOptions{
67 .install_dir = .Lib,68 .source_dir = "lib",
68 .install_subdir = "zig",69 .install_dir = .Lib,
69 .exclude_extensions = &[_][]const u8{70 .install_subdir = "zig",
70 "test.zig",71 .exclude_extensions = &[_][]const u8{
71 "README.md",72 "README.md",
72 ".z.0",73 ".z.0",
73 ".z.9",74 ".z.9",
74 ".gz",75 ".gz",
75 "rfc1951.txt",76 "rfc1951.txt",
76 },77 },
77 });78 .blank_extensions = &[_][]const u8{
79 "test.zig",
80 },
81 });
82 }
7883
79 if (only_install_lib_files)84 if (only_install_lib_files)
80 return;85 return;
...@@ -83,6 +88,12 @@ pub fn build(b: *Builder) !void {...@@ -83,6 +88,12 @@ pub fn build(b: *Builder) !void {
83 const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm;88 const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm;
84 const strip = b.option(bool, "strip", "Omit debug information") orelse false;89 const strip = b.option(bool, "strip", "Omit debug information") orelse false;
8590
91 const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: {
92 if (strip) break :blk @as(u32, 0);
93 if (mode != .Debug) break :blk 0;
94 break :blk 4;
95 };
96
86 const main_file = if (is_stage1) "src/stage1.zig" else "src/main.zig";97 const main_file = if (is_stage1) "src/stage1.zig" else "src/main.zig";
8798
88 var exe = b.addExecutable("zig", main_file);99 var exe = b.addExecutable("zig", main_file);
...@@ -93,6 +104,7 @@ pub fn build(b: *Builder) !void {...@@ -93,6 +104,7 @@ pub fn build(b: *Builder) !void {
93 toolchain_step.dependOn(&exe.step);104 toolchain_step.dependOn(&exe.step);
94 b.default_step.dependOn(&exe.step);105 b.default_step.dependOn(&exe.step);
95106
107 exe.addBuildOption(u32, "mem_leak_frames", mem_leak_frames);
96 exe.addBuildOption(bool, "skip_non_native", skip_non_native);108 exe.addBuildOption(bool, "skip_non_native", skip_non_native);
97 exe.addBuildOption(bool, "have_llvm", enable_llvm);109 exe.addBuildOption(bool, "have_llvm", enable_llvm);
98 if (enable_llvm) {110 if (enable_llvm) {
...@@ -228,6 +240,7 @@ pub fn build(b: *Builder) !void {...@@ -228,6 +240,7 @@ pub fn build(b: *Builder) !void {
228 test_stage2.addBuildOption(bool, "enable_qemu", is_qemu_enabled);240 test_stage2.addBuildOption(bool, "enable_qemu", is_qemu_enabled);
229 test_stage2.addBuildOption(bool, "enable_wine", is_wine_enabled);241 test_stage2.addBuildOption(bool, "enable_wine", is_wine_enabled);
230 test_stage2.addBuildOption(bool, "enable_wasmtime", is_wasmtime_enabled);242 test_stage2.addBuildOption(bool, "enable_wasmtime", is_wasmtime_enabled);
243 test_stage2.addBuildOption(u32, "mem_leak_frames", mem_leak_frames * 2);
231 test_stage2.addBuildOption(bool, "enable_darling", is_darling_enabled);244 test_stage2.addBuildOption(bool, "enable_darling", is_darling_enabled);
232 test_stage2.addBuildOption(?[]const u8, "glibc_multi_install_dir", glibc_multi_dir);245 test_stage2.addBuildOption(?[]const u8, "glibc_multi_install_dir", glibc_multi_dir);
233 test_stage2.addBuildOption([]const u8, "version", version);246 test_stage2.addBuildOption([]const u8, "version", version);
...@@ -266,7 +279,7 @@ pub fn build(b: *Builder) !void {...@@ -266,7 +279,7 @@ pub fn build(b: *Builder) !void {
266 toolchain_step.dependOn(tests.addPkgTests(279 toolchain_step.dependOn(tests.addPkgTests(
267 b,280 b,
268 test_filter,281 test_filter,
269 "test/stage1/behavior.zig",282 "test/behavior.zig",
270 "behavior",283 "behavior",
271 "Run the behavior tests",284 "Run the behavior tests",
272 modes,285 modes,
doc/langref.html.in+16-36
...@@ -1099,7 +1099,6 @@ const nan = std.math.nan(f128);...@@ -1099,7 +1099,6 @@ const nan = std.math.nan(f128);
1099 {#code_release_fast#}1099 {#code_release_fast#}
1100 {#code_disable_cache#}1100 {#code_disable_cache#}
1101const std = @import("std");1101const std = @import("std");
1102const builtin = std.builtin;
1103const big = @as(f64, 1 << 40);1102const big = @as(f64, 1 << 40);
11041103
1105export fn foo_strict(x: f64) f64 {1104export fn foo_strict(x: f64) f64 {
...@@ -2589,7 +2588,7 @@ test "default struct initialization fields" {...@@ -2589,7 +2588,7 @@ test "default struct initialization fields" {
2589 exactly their bit width.2588 exactly their bit width.
2590 </li>2589 </li>
2591 <li>{#syntax#}bool{#endsyntax#} fields use exactly 1 bit.</li>2590 <li>{#syntax#}bool{#endsyntax#} fields use exactly 1 bit.</li>
2592 <li>A {#link|packed enum#} field uses exactly the bit width of its integer tag type.</li>2591 <li>An {#link|enum#} field uses exactly the bit width of its integer tag type.</li>
2593 <li>A {#link|packed union#} field uses exactly the bit width of the union field with2592 <li>A {#link|packed union#} field uses exactly the bit width of the union field with
2594 the largest bit width.</li>2593 the largest bit width.</li>
2595 <li>Non-ABI-aligned fields are packed into the smallest possible2594 <li>Non-ABI-aligned fields are packed into the smallest possible
...@@ -2603,7 +2602,7 @@ test "default struct initialization fields" {...@@ -2603,7 +2602,7 @@ test "default struct initialization fields" {
2603 </p>2602 </p>
2604 {#code_begin|test#}2603 {#code_begin|test#}
2605const std = @import("std");2604const std = @import("std");
2606const builtin = std.builtin;2605const native_endian = @import("builtin").target.cpu.arch.endian();
2607const expect = std.testing.expect;2606const expect = std.testing.expect;
26082607
2609const Full = packed struct {2608const Full = packed struct {
...@@ -2625,7 +2624,7 @@ fn doTheTest() !void {...@@ -2625,7 +2624,7 @@ fn doTheTest() !void {
2625 try expect(@sizeOf(Divided) == 2);2624 try expect(@sizeOf(Divided) == 2);
2626 var full = Full{ .number = 0x1234 };2625 var full = Full{ .number = 0x1234 };
2627 var divided = @bitCast(Divided, full);2626 var divided = @bitCast(Divided, full);
2628 switch (builtin.endian) {2627 switch (native_endian) {
2629 .Big => {2628 .Big => {
2630 try expect(divided.half1 == 0x12);2629 try expect(divided.half1 == 0x12);
2631 try expect(divided.quarter3 == 0x3);2630 try expect(divided.quarter3 == 0x3);
...@@ -3015,25 +3014,6 @@ export fn entry(foo: Foo) void { }...@@ -3015,25 +3014,6 @@ export fn entry(foo: Foo) void { }
3015 {#code_end#}3014 {#code_end#}
3016 {#header_close#}3015 {#header_close#}
30173016
3018 {#header_open|packed enum#}
3019 <p>By default, the size of enums is not guaranteed.</p>
3020 <p>{#syntax#}packed enum{#endsyntax#} causes the size of the enum to be the same as the size of the
3021 integer tag type of the enum:</p>
3022 {#code_begin|test#}
3023const std = @import("std");
3024
3025test "packed enum" {
3026 const Number = packed enum(u8) {
3027 one,
3028 two,
3029 three,
3030 };
3031 try std.testing.expect(@sizeOf(Number) == @sizeOf(u8));
3032}
3033 {#code_end#}
3034 <p>This makes the enum eligible to be in a {#link|packed struct#}.</p>
3035 {#header_close#}
3036
3037 {#header_open|Enum Literals#}3017 {#header_open|Enum Literals#}
3038 <p>3018 <p>
3039 Enum literals allow specifying the name of an enum field without specifying the enum type:3019 Enum literals allow specifying the name of an enum field without specifying the enum type:
...@@ -4255,7 +4235,7 @@ test "noreturn" {...@@ -4255,7 +4235,7 @@ test "noreturn" {
4255 <p>Another use case for {#syntax#}noreturn{#endsyntax#} is the {#syntax#}exit{#endsyntax#} function:</p>4235 <p>Another use case for {#syntax#}noreturn{#endsyntax#} is the {#syntax#}exit{#endsyntax#} function:</p>
4256 {#code_begin|test#}4236 {#code_begin|test#}
4257 {#target_windows#}4237 {#target_windows#}
4258pub extern "kernel32" fn ExitProcess(exit_code: c_uint) callconv(if (@import("builtin").arch == .i386) .Stdcall else .C) noreturn;4238pub extern "kernel32" fn ExitProcess(exit_code: c_uint) callconv(if (@import("builtin").target.cpu.arch == .i386) .Stdcall else .C) noreturn;
42594239
4260test "foo" {4240test "foo" {
4261 const value = bar() catch ExitProcess(1);4241 const value = bar() catch ExitProcess(1);
...@@ -4290,7 +4270,7 @@ export fn sub(a: i8, b: i8) i8 { return a - b; }...@@ -4290,7 +4270,7 @@ export fn sub(a: i8, b: i8) i8 { return a - b; }
4290// at link time, when linking statically, or at runtime, when linking4270// at link time, when linking statically, or at runtime, when linking
4291// dynamically.4271// dynamically.
4292// The callconv specifier changes the calling convention of the function.4272// The callconv specifier changes the calling convention of the function.
4293extern "kernel32" fn ExitProcess(exit_code: u32) callconv(if (@import("builtin").arch == .i386) .Stdcall else .C) noreturn;4273extern "kernel32" fn ExitProcess(exit_code: u32) callconv(if (@import("builtin").target.cpu.arch == .i386) .Stdcall else .C) noreturn;
4294extern "c" fn atan2(a: f64, b: f64) f64;4274extern "c" fn atan2(a: f64, b: f64) f64;
42954275
4296// The @setCold builtin tells the optimizer that a function is rarely called.4276// The @setCold builtin tells the optimizer that a function is rarely called.
...@@ -7596,7 +7576,7 @@ export fn @"A function name that is a complete sentence."() void {}...@@ -7596,7 +7576,7 @@ export fn @"A function name that is a complete sentence."() void {}
7596 The {#syntax#}fence{#endsyntax#} function is used to introduce happens-before edges between operations.7576 The {#syntax#}fence{#endsyntax#} function is used to introduce happens-before edges between operations.
7597 </p>7577 </p>
7598 <p>7578 <p>
7599 {#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("builtin").AtomicOrder{#endsyntax#}.7579 {#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.
7600 </p>7580 </p>
7601 {#see_also|Compile Variables#}7581 {#see_also|Compile Variables#}
7602 {#header_close#}7582 {#header_close#}
...@@ -7799,8 +7779,8 @@ test "@hasDecl" {...@@ -7799,8 +7779,8 @@ test "@hasDecl" {
7799 </p>7779 </p>
7800 <ul>7780 <ul>
7801 <li>{#syntax#}@import("std"){#endsyntax#} - Zig Standard Library</li>7781 <li>{#syntax#}@import("std"){#endsyntax#} - Zig Standard Library</li>
7802 <li>{#syntax#}@import("builtin"){#endsyntax#} - Compiler-provided types and variables.7782 <li>{#syntax#}@import("builtin"){#endsyntax#} - Target-specific information
7803 The command <code>zig builtin</code> outputs the source to stdout for reference.7783 The command <code>zig build-exe --show-builtin</code> outputs the source to stdout for reference.
7804 </li>7784 </li>
7805 </ul>7785 </ul>
7806 {#see_also|Compile Variables|@embedFile#}7786 {#see_also|Compile Variables|@embedFile#}
...@@ -7931,11 +7911,11 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>...@@ -7931,11 +7911,11 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
7931 </p>7911 </p>
7932 {#code_begin|test#}7912 {#code_begin|test#}
7933const std = @import("std");7913const std = @import("std");
7934const builtin = @import("builtin");7914const native_arch = @import("builtin").target.cpu.arch;
7935const expect = std.testing.expect;7915const expect = std.testing.expect;
79367916
7937test "@wasmMemoryGrow" {7917test "@wasmMemoryGrow" {
7938 if (builtin.arch != .wasm32) return error.SkipZigTest;7918 if (native_arch != .wasm32) return error.SkipZigTest;
79397919
7940 var prev = @wasmMemorySize(0);7920 var prev = @wasmMemorySize(0);
7941 try expect(prev == @wasmMemoryGrow(0, 1));7921 try expect(prev == @wasmMemoryGrow(0, 1));
...@@ -8103,7 +8083,7 @@ test "foo" {...@@ -8103,7 +8083,7 @@ test "foo" {
8103 {#header_close#}8083 {#header_close#}
81048084
8105 {#header_open|@setFloatMode#}8085 {#header_open|@setFloatMode#}
8106 <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre>8086 <pre>{#syntax#}@setFloatMode(mode: @import("std").builtin.FloatMode){#endsyntax#}</pre>
8107 <p>8087 <p>
8108 Sets the floating point mode of the current scope. Possible values are:8088 Sets the floating point mode of the current scope. Possible values are:
8109 </p>8089 </p>
...@@ -8292,7 +8272,7 @@ test "vector @splat" {...@@ -8292,7 +8272,7 @@ test "vector @splat" {
8292 {#header_close#}8272 {#header_close#}
82938273
8294 {#header_open|@reduce#}8274 {#header_open|@reduce#}
8295 <pre>{#syntax#}@reduce(comptime op: builtin.ReduceOp, value: anytype) std.meta.Child(value){#endsyntax#}</pre>8275 <pre>{#syntax#}@reduce(comptime op: std.builtin.ReduceOp, value: anytype) std.meta.Child(value){#endsyntax#}</pre>
8296 <p>8276 <p>
8297 Transforms a {#link|vector|Vectors#} into a scalar value by performing a8277 Transforms a {#link|vector|Vectors#} into a scalar value by performing a
8298 sequential horizontal reduction of its elements using the specified operator {#syntax#}op{#endsyntax#}.8278 sequential horizontal reduction of its elements using the specified operator {#syntax#}op{#endsyntax#}.
...@@ -8584,7 +8564,7 @@ test "integer truncation" {...@@ -8584,7 +8564,7 @@ test "integer truncation" {
8584 {#header_close#}8564 {#header_close#}
85858565
8586 {#header_open|@Type#}8566 {#header_open|@Type#}
8587 <pre>{#syntax#}@Type(comptime info: @import("builtin").TypeInfo) type{#endsyntax#}</pre>8567 <pre>{#syntax#}@Type(comptime info: std.builtin.TypeInfo) type{#endsyntax#}</pre>
8588 <p>8568 <p>
8589 This function is the inverse of {#link|@typeInfo#}. It reifies type information8569 This function is the inverse of {#link|@typeInfo#}. It reifies type information
8590 into a {#syntax#}type{#endsyntax#}.8570 into a {#syntax#}type{#endsyntax#}.
...@@ -8626,7 +8606,7 @@ test "integer truncation" {...@@ -8626,7 +8606,7 @@ test "integer truncation" {
8626 </ul>8606 </ul>
8627 {#header_close#}8607 {#header_close#}
8628 {#header_open|@typeInfo#}8608 {#header_open|@typeInfo#}
8629 <pre>{#syntax#}@typeInfo(comptime T: type) @import("std").builtin.TypeInfo{#endsyntax#}</pre>8609 <pre>{#syntax#}@typeInfo(comptime T: type) std.builtin.TypeInfo{#endsyntax#}</pre>
8630 <p>8610 <p>
8631 Provides type reflection.8611 Provides type reflection.
8632 </p>8612 </p>
...@@ -9647,7 +9627,7 @@ test "string literal to constant slice" {...@@ -9647,7 +9627,7 @@ test "string literal to constant slice" {
9647 </p>9627 </p>
9648 {#code_begin|syntax#}9628 {#code_begin|syntax#}
9649const builtin = @import("builtin");9629const builtin = @import("builtin");
9650const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';9630const separator = if (builtin.os.tag == builtin.Os.windows) '\\' else '/';
9651 {#code_end#}9631 {#code_end#}
9652 <p>9632 <p>
9653 Example of what is imported with {#syntax#}@import("builtin"){#endsyntax#}:9633 Example of what is imported with {#syntax#}@import("builtin"){#endsyntax#}:
...@@ -9672,7 +9652,7 @@ const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';...@@ -9672,7 +9652,7 @@ const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';
9672 </p>9652 </p>
9673 {#code_begin|test|detect_test#}9653 {#code_begin|test|detect_test#}
9674const std = @import("std");9654const std = @import("std");
9675const builtin = std.builtin;9655const builtin = @import("builtin");
9676const expect = std.testing.expect;9656const expect = std.testing.expect;
96779657
9678test "builtin.is_test" {9658test "builtin.is_test" {
lib/std/Thread/AutoResetEvent.zig+1-1
...@@ -32,7 +32,7 @@...@@ -32,7 +32,7 @@
32state: usize = UNSET,32state: usize = UNSET,
3333
34const std = @import("../std.zig");34const std = @import("../std.zig");
35const builtin = @import("builtin");35const builtin = std.builtin;
36const testing = std.testing;36const testing = std.testing;
37const assert = std.debug.assert;37const assert = std.debug.assert;
38const StaticResetEvent = std.Thread.StaticResetEvent;38const StaticResetEvent = std.Thread.StaticResetEvent;
lib/std/Thread/StaticResetEvent.zig+2-2
...@@ -262,7 +262,7 @@ pub const AtomicEvent = struct {...@@ -262,7 +262,7 @@ pub const AtomicEvent = struct {
262 while (true) {262 while (true) {
263 if (waiting == WAKE) {263 if (waiting == WAKE) {
264 rc = windows.ntdll.NtWaitForKeyedEvent(handle, key, windows.FALSE, null);264 rc = windows.ntdll.NtWaitForKeyedEvent(handle, key, windows.FALSE, null);
265 assert(rc == .WAIT_0);265 assert(rc == windows.NTSTATUS.WAIT_0);
266 break;266 break;
267 } else {267 } else {
268 waiting = @cmpxchgWeak(u32, waiters, waiting, waiting - WAIT, .Acquire, .Monotonic) orelse break;268 waiting = @cmpxchgWeak(u32, waiters, waiting, waiting - WAIT, .Acquire, .Monotonic) orelse break;
...@@ -271,7 +271,7 @@ pub const AtomicEvent = struct {...@@ -271,7 +271,7 @@ pub const AtomicEvent = struct {
271 }271 }
272 return error.TimedOut;272 return error.TimedOut;
273 },273 },
274 .WAIT_0 => {},274 windows.NTSTATUS.WAIT_0 => {},
275 else => unreachable,275 else => unreachable,
276 }276 }
277 }277 }
lib/std/array_hash_map.zig+30-6
...@@ -14,7 +14,7 @@ const trait = meta.trait;...@@ -14,7 +14,7 @@ const trait = meta.trait;
14const autoHash = std.hash.autoHash;14const autoHash = std.hash.autoHash;
15const Wyhash = std.hash.Wyhash;15const Wyhash = std.hash.Wyhash;
16const Allocator = mem.Allocator;16const Allocator = mem.Allocator;
17const builtin = @import("builtin");17const builtin = std.builtin;
18const hash_map = @This();18const hash_map = @This();
1919
20pub fn AutoArrayHashMap(comptime K: type, comptime V: type) type {20pub fn AutoArrayHashMap(comptime K: type, comptime V: type) type {
...@@ -158,10 +158,20 @@ pub fn ArrayHashMap(...@@ -158,10 +158,20 @@ pub fn ArrayHashMap(
158 return self.unmanaged.getOrPutValue(self.allocator, key, value);158 return self.unmanaged.getOrPutValue(self.allocator, key, value);
159 }159 }
160160
161 /// Deprecated: call `ensureUnusedCapacity` or `ensureTotalCapacity`.
162 pub const ensureCapacity = ensureTotalCapacity;
163
161 /// Increases capacity, guaranteeing that insertions up until the164 /// Increases capacity, guaranteeing that insertions up until the
162 /// `expected_count` will not cause an allocation, and therefore cannot fail.165 /// `expected_count` will not cause an allocation, and therefore cannot fail.
163 pub fn ensureCapacity(self: *Self, new_capacity: usize) !void {166 pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) !void {
164 return self.unmanaged.ensureCapacity(self.allocator, new_capacity);167 return self.unmanaged.ensureTotalCapacity(self.allocator, new_capacity);
168 }
169
170 /// Increases capacity, guaranteeing that insertions up until
171 /// `additional_count` **more** items will not cause an allocation, and
172 /// therefore cannot fail.
173 pub fn ensureUnusedCapacity(self: *Self, additional_count: usize) !void {
174 return self.unmanaged.ensureUnusedCapacity(self.allocator, additional_count);
165 }175 }
166176
167 /// Returns the number of total elements which may be present before it is177 /// Returns the number of total elements which may be present before it is
...@@ -472,10 +482,13 @@ pub fn ArrayHashMapUnmanaged(...@@ -472,10 +482,13 @@ pub fn ArrayHashMapUnmanaged(
472 return res.entry;482 return res.entry;
473 }483 }
474484
485 /// Deprecated: call `ensureUnusedCapacity` or `ensureTotalCapacity`.
486 pub const ensureCapacity = ensureTotalCapacity;
487
475 /// Increases capacity, guaranteeing that insertions up until the488 /// Increases capacity, guaranteeing that insertions up until the
476 /// `expected_count` will not cause an allocation, and therefore cannot fail.489 /// `expected_count` will not cause an allocation, and therefore cannot fail.
477 pub fn ensureCapacity(self: *Self, allocator: *Allocator, new_capacity: usize) !void {490 pub fn ensureTotalCapacity(self: *Self, allocator: *Allocator, new_capacity: usize) !void {
478 try self.entries.ensureCapacity(allocator, new_capacity);491 try self.entries.ensureTotalCapacity(allocator, new_capacity);
479 if (new_capacity <= linear_scan_max) return;492 if (new_capacity <= linear_scan_max) return;
480493
481 // Ensure that the indexes will be at most 60% full if494 // Ensure that the indexes will be at most 60% full if
...@@ -501,6 +514,17 @@ pub fn ArrayHashMapUnmanaged(...@@ -501,6 +514,17 @@ pub fn ArrayHashMapUnmanaged(
501 }514 }
502 }515 }
503516
517 /// Increases capacity, guaranteeing that insertions up until
518 /// `additional_count` **more** items will not cause an allocation, and
519 /// therefore cannot fail.
520 pub fn ensureUnusedCapacity(
521 self: *Self,
522 allocator: *Allocator,
523 additional_capacity: usize,
524 ) !void {
525 return self.ensureTotalCapacity(allocator, self.count() + additional_capacity);
526 }
527
504 /// Returns the number of total elements which may be present before it is528 /// Returns the number of total elements which may be present before it is
505 /// no longer guaranteed that no allocations will be performed.529 /// no longer guaranteed that no allocations will be performed.
506 pub fn capacity(self: Self) usize {530 pub fn capacity(self: Self) usize {
...@@ -1310,7 +1334,7 @@ test "reIndex" {...@@ -1310,7 +1334,7 @@ test "reIndex" {
1310}1334}
13111335
1312test "fromOwnedArrayList" {1336test "fromOwnedArrayList" {
1313 comptime const array_hash_map_type = AutoArrayHashMap(i32, i32);1337 const array_hash_map_type = AutoArrayHashMap(i32, i32);
1314 var al = std.ArrayListUnmanaged(array_hash_map_type.Entry){};1338 var al = std.ArrayListUnmanaged(array_hash_map_type.Entry){};
1315 const hash = getAutoHashFn(i32);1339 const hash = getAutoHashFn(i32);
13161340
lib/std/array_list.zig+60-14
...@@ -131,7 +131,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -131,7 +131,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
131 /// Insert `item` at index `n` by moving `list[n .. list.len]` to make room.131 /// Insert `item` at index `n` by moving `list[n .. list.len]` to make room.
132 /// This operation is O(N).132 /// This operation is O(N).
133 pub fn insert(self: *Self, n: usize, item: T) !void {133 pub fn insert(self: *Self, n: usize, item: T) !void {
134 try self.ensureCapacity(self.items.len + 1);134 try self.ensureUnusedCapacity(1);
135 self.items.len += 1;135 self.items.len += 1;
136136
137 mem.copyBackwards(T, self.items[n + 1 .. self.items.len], self.items[n .. self.items.len - 1]);137 mem.copyBackwards(T, self.items[n + 1 .. self.items.len], self.items[n .. self.items.len - 1]);
...@@ -141,7 +141,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -141,7 +141,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
141 /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.141 /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.
142 /// This operation is O(N).142 /// This operation is O(N).
143 pub fn insertSlice(self: *Self, i: usize, items: []const T) !void {143 pub fn insertSlice(self: *Self, i: usize, items: []const T) !void {
144 try self.ensureCapacity(self.items.len + items.len);144 try self.ensureUnusedCapacity(items.len);
145 self.items.len += items.len;145 self.items.len += items.len;
146146
147 mem.copyBackwards(T, self.items[i + items.len .. self.items.len], self.items[i .. self.items.len - items.len]);147 mem.copyBackwards(T, self.items[i + items.len .. self.items.len], self.items[i .. self.items.len - items.len]);
...@@ -220,7 +220,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -220,7 +220,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
220 /// Append the slice of items to the list. Allocates more220 /// Append the slice of items to the list. Allocates more
221 /// memory as necessary.221 /// memory as necessary.
222 pub fn appendSlice(self: *Self, items: []const T) !void {222 pub fn appendSlice(self: *Self, items: []const T) !void {
223 try self.ensureCapacity(self.items.len + items.len);223 try self.ensureUnusedCapacity(items.len);
224 self.appendSliceAssumeCapacity(items);224 self.appendSliceAssumeCapacity(items);
225 }225 }
226226
...@@ -269,7 +269,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -269,7 +269,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
269 /// Adjust the list's length to `new_len`.269 /// Adjust the list's length to `new_len`.
270 /// Does not initialize added items if any.270 /// Does not initialize added items if any.
271 pub fn resize(self: *Self, new_len: usize) !void {271 pub fn resize(self: *Self, new_len: usize) !void {
272 try self.ensureCapacity(new_len);272 try self.ensureTotalCapacity(new_len);
273 self.items.len = new_len;273 self.items.len = new_len;
274 }274 }
275275
...@@ -294,9 +294,24 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -294,9 +294,24 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
294 self.items.len = new_len;294 self.items.len = new_len;
295 }295 }
296296
297 /// Invalidates all element pointers.
298 pub fn clearRetainingCapacity(self: *Self) void {
299 self.items.len = 0;
300 }
301
302 /// Invalidates all element pointers.
303 pub fn clearAndFree(self: *Self) void {
304 self.allocator.free(self.allocatedSlice());
305 self.items.len = 0;
306 self.capacity = 0;
307 }
308
309 /// Deprecated: call `ensureUnusedCapacity` or `ensureTotalCapacity`.
310 pub const ensureCapacity = ensureTotalCapacity;
311
297 /// Modify the array so that it can hold at least `new_capacity` items.312 /// Modify the array so that it can hold at least `new_capacity` items.
298 /// Invalidates pointers if additional memory is needed.313 /// Invalidates pointers if additional memory is needed.
299 pub fn ensureCapacity(self: *Self, new_capacity: usize) !void {314 pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) !void {
300 var better_capacity = self.capacity;315 var better_capacity = self.capacity;
301 if (better_capacity >= new_capacity) return;316 if (better_capacity >= new_capacity) return;
302317
...@@ -311,6 +326,12 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -311,6 +326,12 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
311 self.capacity = new_memory.len;326 self.capacity = new_memory.len;
312 }327 }
313328
329 /// Modify the array so that it can hold at least `additional_count` **more** items.
330 /// Invalidates pointers if additional memory is needed.
331 pub fn ensureUnusedCapacity(self: *Self, additional_count: usize) !void {
332 return self.ensureTotalCapacity(self.items.len + additional_count);
333 }
334
314 /// Increases the array's length to match the full capacity that is already allocated.335 /// Increases the array's length to match the full capacity that is already allocated.
315 /// The new elements have `undefined` values. **Does not** invalidate pointers.336 /// The new elements have `undefined` values. **Does not** invalidate pointers.
316 pub fn expandToCapacity(self: *Self) void {337 pub fn expandToCapacity(self: *Self) void {
...@@ -321,7 +342,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -321,7 +342,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
321 /// The returned pointer becomes invalid when the list resized.342 /// The returned pointer becomes invalid when the list resized.
322 pub fn addOne(self: *Self) !*T {343 pub fn addOne(self: *Self) !*T {
323 const newlen = self.items.len + 1;344 const newlen = self.items.len + 1;
324 try self.ensureCapacity(newlen);345 try self.ensureTotalCapacity(newlen);
325 return self.addOneAssumeCapacity();346 return self.addOneAssumeCapacity();
326 }347 }
327348
...@@ -471,7 +492,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -471,7 +492,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
471 /// to higher indices to make room.492 /// to higher indices to make room.
472 /// This operation is O(N).493 /// This operation is O(N).
473 pub fn insert(self: *Self, allocator: *Allocator, n: usize, item: T) !void {494 pub fn insert(self: *Self, allocator: *Allocator, n: usize, item: T) !void {
474 try self.ensureCapacity(allocator, self.items.len + 1);495 try self.ensureUnusedCapacity(allocator, 1);
475 self.items.len += 1;496 self.items.len += 1;
476497
477 mem.copyBackwards(T, self.items[n + 1 .. self.items.len], self.items[n .. self.items.len - 1]);498 mem.copyBackwards(T, self.items[n + 1 .. self.items.len], self.items[n .. self.items.len - 1]);
...@@ -482,7 +503,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -482,7 +503,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
482 /// higher indicices make room.503 /// higher indicices make room.
483 /// This operation is O(N).504 /// This operation is O(N).
484 pub fn insertSlice(self: *Self, allocator: *Allocator, i: usize, items: []const T) !void {505 pub fn insertSlice(self: *Self, allocator: *Allocator, i: usize, items: []const T) !void {
485 try self.ensureCapacity(allocator, self.items.len + items.len);506 try self.ensureUnusedCapacity(allocator, items.len);
486 self.items.len += items.len;507 self.items.len += items.len;
487508
488 mem.copyBackwards(T, self.items[i + items.len .. self.items.len], self.items[i .. self.items.len - items.len]);509 mem.copyBackwards(T, self.items[i + items.len .. self.items.len], self.items[i .. self.items.len - items.len]);
...@@ -542,7 +563,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -542,7 +563,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
542 /// Append the slice of items to the list. Allocates more563 /// Append the slice of items to the list. Allocates more
543 /// memory as necessary.564 /// memory as necessary.
544 pub fn appendSlice(self: *Self, allocator: *Allocator, items: []const T) !void {565 pub fn appendSlice(self: *Self, allocator: *Allocator, items: []const T) !void {
545 try self.ensureCapacity(allocator, self.items.len + items.len);566 try self.ensureUnusedCapacity(allocator, items.len);
546 self.appendSliceAssumeCapacity(items);567 self.appendSliceAssumeCapacity(items);
547 }568 }
548569
...@@ -577,7 +598,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -577,7 +598,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
577 /// Adjust the list's length to `new_len`.598 /// Adjust the list's length to `new_len`.
578 /// Does not initialize added items, if any.599 /// Does not initialize added items, if any.
579 pub fn resize(self: *Self, allocator: *Allocator, new_len: usize) !void {600 pub fn resize(self: *Self, allocator: *Allocator, new_len: usize) !void {
580 try self.ensureCapacity(allocator, new_len);601 try self.ensureTotalCapacity(allocator, new_len);
581 self.items.len = new_len;602 self.items.len = new_len;
582 }603 }
583604
...@@ -602,9 +623,24 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -602,9 +623,24 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
602 self.items.len = new_len;623 self.items.len = new_len;
603 }624 }
604625
626 /// Invalidates all element pointers.
627 pub fn clearRetainingCapacity(self: *Self) void {
628 self.items.len = 0;
629 }
630
631 /// Invalidates all element pointers.
632 pub fn clearAndFree(self: *Self, allocator: *Allocator) void {
633 allocator.free(self.allocatedSlice());
634 self.items.len = 0;
635 self.capacity = 0;
636 }
637
638 /// Deprecated: call `ensureUnusedCapacity` or `ensureTotalCapacity`.
639 pub const ensureCapacity = ensureTotalCapacity;
640
605 /// Modify the array so that it can hold at least `new_capacity` items.641 /// Modify the array so that it can hold at least `new_capacity` items.
606 /// Invalidates pointers if additional memory is needed.642 /// Invalidates pointers if additional memory is needed.
607 pub fn ensureCapacity(self: *Self, allocator: *Allocator, new_capacity: usize) !void {643 pub fn ensureTotalCapacity(self: *Self, allocator: *Allocator, new_capacity: usize) !void {
608 var better_capacity = self.capacity;644 var better_capacity = self.capacity;
609 if (better_capacity >= new_capacity) return;645 if (better_capacity >= new_capacity) return;
610646
...@@ -618,6 +654,16 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -618,6 +654,16 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
618 self.capacity = new_memory.len;654 self.capacity = new_memory.len;
619 }655 }
620656
657 /// Modify the array so that it can hold at least `additional_count` **more** items.
658 /// Invalidates pointers if additional memory is needed.
659 pub fn ensureUnusedCapacity(
660 self: *Self,
661 allocator: *Allocator,
662 additional_count: usize,
663 ) !void {
664 return self.ensureTotalCapacity(allocator, self.items.len + additional_count);
665 }
666
621 /// Increases the array's length to match the full capacity that is already allocated.667 /// Increases the array's length to match the full capacity that is already allocated.
622 /// The new elements have `undefined` values.668 /// The new elements have `undefined` values.
623 /// **Does not** invalidate pointers.669 /// **Does not** invalidate pointers.
...@@ -629,7 +675,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -629,7 +675,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
629 /// The returned pointer becomes invalid when the list resized.675 /// The returned pointer becomes invalid when the list resized.
630 pub fn addOne(self: *Self, allocator: *Allocator) !*T {676 pub fn addOne(self: *Self, allocator: *Allocator) !*T {
631 const newlen = self.items.len + 1;677 const newlen = self.items.len + 1;
632 try self.ensureCapacity(allocator, newlen);678 try self.ensureTotalCapacity(allocator, newlen);
633 return self.addOneAssumeCapacity();679 return self.addOneAssumeCapacity();
634 }680 }
635681
...@@ -1188,7 +1234,7 @@ test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {...@@ -1188,7 +1234,7 @@ test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {
1188 defer list.deinit();1234 defer list.deinit();
11891235
1190 (try list.addManyAsArray(4)).* = "aoeu".*;1236 (try list.addManyAsArray(4)).* = "aoeu".*;
1191 try list.ensureCapacity(8);1237 try list.ensureTotalCapacity(8);
1192 list.addManyAsArrayAssumeCapacity(4).* = "asdf".*;1238 list.addManyAsArrayAssumeCapacity(4).* = "asdf".*;
11931239
1194 try testing.expectEqualSlices(u8, list.items, "aoeuasdf");1240 try testing.expectEqualSlices(u8, list.items, "aoeuasdf");
...@@ -1198,7 +1244,7 @@ test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {...@@ -1198,7 +1244,7 @@ test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {
1198 defer list.deinit(a);1244 defer list.deinit(a);
11991245
1200 (try list.addManyAsArray(a, 4)).* = "aoeu".*;1246 (try list.addManyAsArray(a, 4)).* = "aoeu".*;
1201 try list.ensureCapacity(a, 8);1247 try list.ensureTotalCapacity(a, 8);
1202 list.addManyAsArrayAssumeCapacity(4).* = "asdf".*;1248 list.addManyAsArrayAssumeCapacity(4).* = "asdf".*;
12031249
1204 try testing.expectEqualSlices(u8, list.items, "aoeuasdf");1250 try testing.expectEqualSlices(u8, list.items, "aoeuasdf");
lib/std/atomic/queue.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const assert = std.debug.assert;8const assert = std.debug.assert;
9const expect = std.testing.expect;9const expect = std.testing.expect;
1010
lib/std/atomic/stack.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const assert = std.debug.assert;6const assert = std.debug.assert;
7const builtin = @import("builtin");7const builtin = std.builtin;
8const expect = std.testing.expect;8const expect = std.testing.expect;
99
10/// Many reader, many writer, non-allocating, thread-safe10/// Many reader, many writer, non-allocating, thread-safe
lib/std/build.zig+46-11
...@@ -1019,6 +1019,23 @@ pub const Builder = struct {...@@ -1019,6 +1019,23 @@ pub const Builder = struct {
1019 };1019 };
1020 }1020 }
10211021
1022 pub fn truncateFile(self: *Builder, dest_path: []const u8) !void {
1023 if (self.verbose) {
1024 warn("truncate {s}\n", .{dest_path});
1025 }
1026 const cwd = fs.cwd();
1027 var src_file = cwd.createFile(dest_path, .{}) catch |err| switch (err) {
1028 error.FileNotFound => blk: {
1029 if (fs.path.dirname(dest_path)) |dirname| {
1030 try cwd.makePath(dirname);
1031 }
1032 break :blk try cwd.createFile(dest_path, .{});
1033 },
1034 else => |e| return e,
1035 };
1036 src_file.close();
1037 }
1038
1022 pub fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 {1039 pub fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 {
1023 return fs.path.resolve(self.allocator, &[_][]const u8{ self.build_root, rel_path }) catch unreachable;1040 return fs.path.resolve(self.allocator, &[_][]const u8{ self.build_root, rel_path }) catch unreachable;
1024 }1041 }
...@@ -1415,7 +1432,7 @@ pub const LibExeObjStep = struct {...@@ -1415,7 +1432,7 @@ pub const LibExeObjStep = struct {
14151432
1416 red_zone: ?bool = null,1433 red_zone: ?bool = null,
14171434
1418 subsystem: ?builtin.SubSystem = null,1435 subsystem: ?std.Target.SubSystem = null,
14191436
1420 /// Overrides the default stack size1437 /// Overrides the default stack size
1421 stack_size: ?u64 = null,1438 stack_size: ?u64 = null,
...@@ -1967,7 +1984,7 @@ pub const LibExeObjStep = struct {...@@ -1967,7 +1984,7 @@ pub const LibExeObjStep = struct {
1967 },1984 },
1968 std.builtin.Version => {1985 std.builtin.Version => {
1969 out.print(1986 out.print(
1970 \\pub const {}: @import("builtin").Version = .{{1987 \\pub const {}: @import("std").builtin.Version = .{{
1971 \\ .major = {d},1988 \\ .major = {d},
1972 \\ .minor = {d},1989 \\ .minor = {d},
1973 \\ .patch = {d},1990 \\ .patch = {d},
...@@ -2791,17 +2808,23 @@ pub const InstallDirectoryOptions = struct {...@@ -2791,17 +2808,23 @@ pub const InstallDirectoryOptions = struct {
2791 source_dir: []const u8,2808 source_dir: []const u8,
2792 install_dir: InstallDir,2809 install_dir: InstallDir,
2793 install_subdir: []const u8,2810 install_subdir: []const u8,
2794 exclude_extensions: ?[]const []const u8 = null,2811 /// File paths which end in any of these suffixes will be excluded
2812 /// from being installed.
2813 exclude_extensions: []const []const u8 = &.{},
2814 /// File paths which end in any of these suffixes will result in
2815 /// empty files being installed. This is mainly intended for large
2816 /// test.zig files in order to prevent needless installation bloat.
2817 /// However if the files were not present at all, then
2818 /// `@import("test.zig")` would be a compile error.
2819 blank_extensions: []const []const u8 = &.{},
27952820
2796 fn dupe(self: InstallDirectoryOptions, b: *Builder) InstallDirectoryOptions {2821 fn dupe(self: InstallDirectoryOptions, b: *Builder) InstallDirectoryOptions {
2797 return .{2822 return .{
2798 .source_dir = b.dupe(self.source_dir),2823 .source_dir = b.dupe(self.source_dir),
2799 .install_dir = self.install_dir.dupe(b),2824 .install_dir = self.install_dir.dupe(b),
2800 .install_subdir = b.dupe(self.install_subdir),2825 .install_subdir = b.dupe(self.install_subdir),
2801 .exclude_extensions = if (self.exclude_extensions) |extensions|2826 .exclude_extensions = b.dupeStrings(self.exclude_extensions),
2802 b.dupeStrings(extensions)2827 .blank_extensions = b.dupeStrings(self.blank_extensions),
2803 else
2804 null,
2805 };2828 };
2806 }2829 }
2807};2830};
...@@ -2829,17 +2852,29 @@ pub const InstallDirStep = struct {...@@ -2829,17 +2852,29 @@ pub const InstallDirStep = struct {
2829 const full_src_dir = self.builder.pathFromRoot(self.options.source_dir);2852 const full_src_dir = self.builder.pathFromRoot(self.options.source_dir);
2830 var it = try fs.walkPath(self.builder.allocator, full_src_dir);2853 var it = try fs.walkPath(self.builder.allocator, full_src_dir);
2831 next_entry: while (try it.next()) |entry| {2854 next_entry: while (try it.next()) |entry| {
2832 if (self.options.exclude_extensions) |ext_list| for (ext_list) |ext| {2855 for (self.options.exclude_extensions) |ext| {
2833 if (mem.endsWith(u8, entry.path, ext)) {2856 if (mem.endsWith(u8, entry.path, ext)) {
2834 continue :next_entry;2857 continue :next_entry;
2835 }2858 }
2836 };2859 }
28372860
2838 const rel_path = entry.path[full_src_dir.len + 1 ..];2861 const rel_path = entry.path[full_src_dir.len + 1 ..];
2839 const dest_path = try fs.path.join(self.builder.allocator, &[_][]const u8{ dest_prefix, rel_path });2862 const dest_path = try fs.path.join(self.builder.allocator, &[_][]const u8{
2863 dest_prefix, rel_path,
2864 });
2865
2840 switch (entry.kind) {2866 switch (entry.kind) {
2841 .Directory => try fs.cwd().makePath(dest_path),2867 .Directory => try fs.cwd().makePath(dest_path),
2842 .File => try self.builder.updateFile(entry.path, dest_path),2868 .File => {
2869 for (self.options.blank_extensions) |ext| {
2870 if (mem.endsWith(u8, entry.path, ext)) {
2871 try self.builder.truncateFile(dest_path);
2872 continue :next_entry;
2873 }
2874 }
2875
2876 try self.builder.updateFile(entry.path, dest_path);
2877 },
2843 else => continue,2878 else => continue,
2844 }2879 }
2845 }2880 }
lib/std/builtin.zig+29-28
...@@ -3,39 +3,40 @@...@@ -3,39 +3,40 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6pub usingnamespace @import("builtin");6const builtin = @import("builtin");
77
8/// Deprecated: use `std.Target`.8// These are all deprecated.
9pub const Target = std.Target;9pub const zig_version = builtin.zig_version;
1010pub const zig_is_stage2 = builtin.zig_is_stage2;
11/// Deprecated: use `std.Target.Os`.11pub const output_mode = builtin.output_mode;
12pub const Os = std.Target.Os;12pub const link_mode = builtin.link_mode;
1313pub const is_test = builtin.is_test;
14/// Deprecated: use `std.Target.Cpu.Arch`.14pub const single_threaded = builtin.single_threaded;
15pub const Arch = std.Target.Cpu.Arch;15pub const abi = builtin.abi;
1616pub const cpu = builtin.cpu;
17/// Deprecated: use `std.Target.Abi`.17pub const os = builtin.os;
18pub const Abi = std.Target.Abi;18pub const target = builtin.target;
1919pub const object_format = builtin.object_format;
20/// Deprecated: use `std.Target.ObjectFormat`.20pub const mode = builtin.mode;
21pub const ObjectFormat = std.Target.ObjectFormat;21pub const link_libc = builtin.link_libc;
2222pub const link_libcpp = builtin.link_libcpp;
23/// Deprecated: use `std.Target.SubSystem`.23pub const have_error_return_tracing = builtin.have_error_return_tracing;
24pub const SubSystem = std.Target.SubSystem;24pub const valgrind_support = builtin.valgrind_support;
2525pub const position_independent_code = builtin.position_independent_code;
26/// Deprecated: use `std.Target.Cpu`.26pub const position_independent_executable = builtin.position_independent_executable;
27pub const Cpu = std.Target.Cpu;27pub const strip_debug_info = builtin.strip_debug_info;
28pub const code_model = builtin.code_model;
2829
29/// `explicit_subsystem` is missing when the subsystem is automatically detected,30/// `explicit_subsystem` is missing when the subsystem is automatically detected,
30/// so Zig standard library has the subsystem detection logic here. This should generally be31/// so Zig standard library has the subsystem detection logic here. This should generally be
31/// used rather than `explicit_subsystem`.32/// used rather than `explicit_subsystem`.
32/// On non-Windows targets, this is `null`.33/// On non-Windows targets, this is `null`.
33pub const subsystem: ?SubSystem = blk: {34pub const subsystem: ?std.Target.SubSystem = blk: {
34 if (@hasDecl(@This(), "explicit_subsystem")) break :blk explicit_subsystem;35 if (@hasDecl(builtin, "explicit_subsystem")) break :blk explicit_subsystem;
35 switch (os.tag) {36 switch (os.tag) {
36 .windows => {37 .windows => {
37 if (is_test) {38 if (is_test) {
38 break :blk SubSystem.Console;39 break :blk std.Target.SubSystem.Console;
39 }40 }
40 if (@hasDecl(root, "main") or41 if (@hasDecl(root, "main") or
41 @hasDecl(root, "WinMain") or42 @hasDecl(root, "WinMain") or
...@@ -43,9 +44,9 @@ pub const subsystem: ?SubSystem = blk: {...@@ -43,9 +44,9 @@ pub const subsystem: ?SubSystem = blk: {
43 @hasDecl(root, "WinMainCRTStartup") or44 @hasDecl(root, "WinMainCRTStartup") or
44 @hasDecl(root, "wWinMainCRTStartup"))45 @hasDecl(root, "wWinMainCRTStartup"))
45 {46 {
46 break :blk SubSystem.Windows;47 break :blk std.Target.SubSystem.Windows;
47 } else {48 } else {
48 break :blk SubSystem.Console;49 break :blk std.Target.SubSystem.Console;
49 }50 }
50 },51 },
51 else => break :blk null,52 else => break :blk null,
...@@ -262,7 +263,7 @@ pub const TypeInfo = union(enum) {...@@ -262,7 +263,7 @@ pub const TypeInfo = union(enum) {
262263
263 /// This data structure is used by the Zig language code generation and264 /// This data structure is used by the Zig language code generation and
264 /// therefore must be kept in sync with the compiler implementation.265 /// therefore must be kept in sync with the compiler implementation.
265 pub const ContainerLayout = enum {266 pub const ContainerLayout = enum(u2) {
266 Auto,267 Auto,
267 Extern,268 Extern,
268 Packed,269 Packed,
lib/std/c/darwin.zig+4-3
...@@ -7,6 +7,7 @@ const std = @import("../std.zig");...@@ -7,6 +7,7 @@ const std = @import("../std.zig");
7const assert = std.debug.assert;7const assert = std.debug.assert;
8const builtin = @import("builtin");8const builtin = @import("builtin");
9const macho = std.macho;9const macho = std.macho;
10const native_arch = builtin.target.cpu.arch;
1011
11usingnamespace @import("../os/bits.zig");12usingnamespace @import("../os/bits.zig");
1213
...@@ -34,13 +35,13 @@ extern "c" fn fstat(fd: fd_t, buf: *libc_stat) c_int;...@@ -34,13 +35,13 @@ extern "c" fn fstat(fd: fd_t, buf: *libc_stat) c_int;
34/// On x86_64 Darwin, fstat has to be manully linked with $INODE64 suffix to force 64bit version.35/// On x86_64 Darwin, fstat has to be manully linked with $INODE64 suffix to force 64bit version.
35/// Note that this is fixed on aarch64 and no longer necessary.36/// Note that this is fixed on aarch64 and no longer necessary.
36extern "c" fn @"fstat$INODE64"(fd: fd_t, buf: *libc_stat) c_int;37extern "c" fn @"fstat$INODE64"(fd: fd_t, buf: *libc_stat) c_int;
37pub const _fstat = if (builtin.arch == .aarch64) fstat else @"fstat$INODE64";38pub const _fstat = if (native_arch == .aarch64) fstat else @"fstat$INODE64";
3839
39extern "c" fn fstatat(dirfd: fd_t, path: [*:0]const u8, stat_buf: *libc_stat, flags: u32) c_int;40extern "c" fn fstatat(dirfd: fd_t, path: [*:0]const u8, stat_buf: *libc_stat, flags: u32) c_int;
40/// On x86_64 Darwin, fstatat has to be manully linked with $INODE64 suffix to force 64bit version.41/// On x86_64 Darwin, fstatat has to be manully linked with $INODE64 suffix to force 64bit version.
41/// Note that this is fixed on aarch64 and no longer necessary.42/// Note that this is fixed on aarch64 and no longer necessary.
42extern "c" fn @"fstatat$INODE64"(dirfd: fd_t, path_name: [*:0]const u8, buf: *libc_stat, flags: u32) c_int;43extern "c" fn @"fstatat$INODE64"(dirfd: fd_t, path_name: [*:0]const u8, buf: *libc_stat, flags: u32) c_int;
43pub const _fstatat = if (builtin.arch == .aarch64) fstatat else @"fstatat$INODE64";44pub const _fstatat = if (native_arch == .aarch64) fstatat else @"fstatat$INODE64";
4445
45pub extern "c" fn mach_absolute_time() u64;46pub extern "c" fn mach_absolute_time() u64;
46pub extern "c" fn mach_timebase_info(tinfo: ?*mach_timebase_info_data) void;47pub extern "c" fn mach_timebase_info(tinfo: ?*mach_timebase_info_data) void;
...@@ -121,7 +122,7 @@ pub const AI_NUMERICHOST = 0x00000004;...@@ -121,7 +122,7 @@ pub const AI_NUMERICHOST = 0x00000004;
121/// prevent service name resolution122/// prevent service name resolution
122pub const AI_NUMERICSERV = 0x00001000;123pub const AI_NUMERICSERV = 0x00001000;
123124
124pub const EAI = extern enum(c_int) {125pub const EAI = enum(c_int) {
125 /// address family for hostname not supported126 /// address family for hostname not supported
126 ADDRFAMILY = 1,127 ADDRFAMILY = 1,
127128
lib/std/c/freebsd.zig+1-1
...@@ -62,7 +62,7 @@ pub const sem_t = extern struct {...@@ -62,7 +62,7 @@ pub const sem_t = extern struct {
62 _padding: u32,62 _padding: u32,
63};63};
6464
65pub const EAI = extern enum(c_int) {65pub const EAI = enum(c_int) {
66 /// address family for hostname not supported66 /// address family for hostname not supported
67 ADDRFAMILY = 1,67 ADDRFAMILY = 1,
6868
lib/std/c/haiku.zig+1-1
...@@ -70,7 +70,7 @@ pub const pthread_rwlock_t = extern struct {...@@ -70,7 +70,7 @@ pub const pthread_rwlock_t = extern struct {
70 waiters: [2]?*c_void = [_]?*c_void{ null, null },70 waiters: [2]?*c_void = [_]?*c_void{ null, null },
71};71};
7272
73pub const EAI = extern enum(c_int) {73pub const EAI = enum(c_int) {
74 /// address family for hostname not supported74 /// address family for hostname not supported
75 ADDRFAMILY = 1,75 ADDRFAMILY = 1,
7676
lib/std/c/linux.zig+9-7
...@@ -3,12 +3,14 @@...@@ -3,12 +3,14 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");
7const std = @import("../std.zig");6const std = @import("../std.zig");
8const maxInt = std.math.maxInt;7const maxInt = std.math.maxInt;
8const abi = std.Target.current.abi;
9const arch = std.Target.current.cpu.arch;
10const os_tag = std.Target.current.os.tag;
9usingnamespace std.c;11usingnamespace std.c;
1012
11pub const _errno = switch (builtin.abi) {13pub const _errno = switch (abi) {
12 .android => struct {14 .android => struct {
13 extern "c" var __errno: c_int;15 extern "c" var __errno: c_int;
14 fn getErrno() *c_int {16 fn getErrno() *c_int {
...@@ -37,7 +39,7 @@ pub const NI_NAMEREQD = 0x08;...@@ -37,7 +39,7 @@ pub const NI_NAMEREQD = 0x08;
37pub const NI_DGRAM = 0x10;39pub const NI_DGRAM = 0x10;
38pub const NI_NUMERICSCOPE = 0x100;40pub const NI_NUMERICSCOPE = 0x100;
3941
40pub const EAI = extern enum(c_int) {42pub const EAI = enum(c_int) {
41 BADFLAGS = -1,43 BADFLAGS = -1,
42 NONAME = -2,44 NONAME = -2,
43 AGAIN = -3,45 AGAIN = -3,
...@@ -139,7 +141,7 @@ pub const pthread_mutex_t = extern struct {...@@ -139,7 +141,7 @@ pub const pthread_mutex_t = extern struct {
139pub const pthread_cond_t = extern struct {141pub const pthread_cond_t = extern struct {
140 size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T,142 size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T,
141};143};
142pub const pthread_rwlock_t = switch (std.builtin.abi) {144pub const pthread_rwlock_t = switch (abi) {
143 .android => switch (@sizeOf(usize)) {145 .android => switch (@sizeOf(usize)) {
144 4 => extern struct {146 4 => extern struct {
145 lock: std.c.pthread_mutex_t = std.c.PTHREAD_MUTEX_INITIALIZER,147 lock: std.c.pthread_mutex_t = std.c.PTHREAD_MUTEX_INITIALIZER,
...@@ -170,11 +172,11 @@ pub const sem_t = extern struct {...@@ -170,11 +172,11 @@ pub const sem_t = extern struct {
170};172};
171173
172const __SIZEOF_PTHREAD_COND_T = 48;174const __SIZEOF_PTHREAD_COND_T = 48;
173const __SIZEOF_PTHREAD_MUTEX_T = if (builtin.os.tag == .fuchsia) 40 else switch (builtin.abi) {175const __SIZEOF_PTHREAD_MUTEX_T = if (os_tag == .fuchsia) 40 else switch (abi) {
174 .musl, .musleabi, .musleabihf => if (@sizeOf(usize) == 8) 40 else 24,176 .musl, .musleabi, .musleabihf => if (@sizeOf(usize) == 8) 40 else 24,
175 .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => switch (builtin.arch) {177 .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => switch (arch) {
176 .aarch64 => 48,178 .aarch64 => 48,
177 .x86_64 => if (builtin.abi == .gnux32) 40 else 32,179 .x86_64 => if (abi == .gnux32) 40 else 32,
178 .mips64, .powerpc64, .powerpc64le, .sparcv9 => 40,180 .mips64, .powerpc64, .powerpc64le, .sparcv9 => 40,
179 else => if (@sizeOf(usize) == 8) 40 else 24,181 else => if (@sizeOf(usize) == 8) 40 else 24,
180 },182 },
lib/std/child_process.zig+1-1
...@@ -15,7 +15,7 @@ const windows = os.windows;...@@ -15,7 +15,7 @@ const windows = os.windows;
15const mem = std.mem;15const mem = std.mem;
16const debug = std.debug;16const debug = std.debug;
17const BufMap = std.BufMap;17const BufMap = std.BufMap;
18const builtin = @import("builtin");18const builtin = std.builtin;
19const Os = builtin.Os;19const Os = builtin.Os;
20const TailQueue = std.TailQueue;20const TailQueue = std.TailQueue;
21const maxInt = std.math.maxInt;21const maxInt = std.math.maxInt;
lib/std/coff.zig+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");6const builtin = std.builtin;
7const std = @import("std.zig");7const std = @import("std.zig");
8const io = std.io;8const io = std.io;
9const mem = std.mem;9const mem = std.mem;
lib/std/crypto/25519/curve25519.zig+1-1
...@@ -102,7 +102,7 @@ pub const Curve25519 = struct {...@@ -102,7 +102,7 @@ pub const Curve25519 = struct {
102 /// key is a low-order point.102 /// key is a low-order point.
103 pub fn mul(p: Curve25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Curve25519 {103 pub fn mul(p: Curve25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Curve25519 {
104 const cofactor = [_]u8{8} ++ [_]u8{0} ** 31;104 const cofactor = [_]u8{8} ++ [_]u8{0} ** 31;
105 _ = ladder(p, cofactor, 4) catch |_| return error.WeakPublicKey;105 _ = ladder(p, cofactor, 4) catch return error.WeakPublicKey;
106 return try ladder(p, s, 256);106 return try ladder(p, s, 256);
107 }107 }
108108
lib/std/crypto/25519/edwards25519.zig+4-4
...@@ -226,12 +226,12 @@ pub const Edwards25519 = struct {...@@ -226,12 +226,12 @@ pub const Edwards25519 = struct {
226 return pc;226 return pc;
227 }227 }
228228
229 const basePointPc = comptime pc: {229 const basePointPc = pc: {
230 @setEvalBranchQuota(10000);230 @setEvalBranchQuota(10000);
231 break :pc precompute(Edwards25519.basePoint, 15);231 break :pc precompute(Edwards25519.basePoint, 15);
232 };232 };
233233
234 const basePointPc8 = comptime pc: {234 const basePointPc8 = pc: {
235 @setEvalBranchQuota(10000);235 @setEvalBranchQuota(10000);
236 break :pc precompute(Edwards25519.basePoint, 8);236 break :pc precompute(Edwards25519.basePoint, 8);
237 };237 };
...@@ -255,7 +255,7 @@ pub const Edwards25519 = struct {...@@ -255,7 +255,7 @@ pub const Edwards25519 = struct {
255 return pcMul16(basePointPc, s, true);255 return pcMul16(basePointPc, s, true);
256 } else {256 } else {
257 const pc = precompute(p, 8);257 const pc = precompute(p, 8);
258 pc[4].rejectIdentity() catch |_| return error.WeakPublicKey;258 pc[4].rejectIdentity() catch return error.WeakPublicKey;
259 return pcMul(pc, s, true);259 return pcMul(pc, s, true);
260 }260 }
261 }261 }
...@@ -306,7 +306,7 @@ pub const Edwards25519 = struct {...@@ -306,7 +306,7 @@ pub const Edwards25519 = struct {
306 pcs[i] = basePointPc8;306 pcs[i] = basePointPc8;
307 } else {307 } else {
308 pcs[i] = precompute(p, 8);308 pcs[i] = precompute(p, 8);
309 pcs[i][4].rejectIdentity() catch |_| return error.WeakPublicKey;309 pcs[i][4].rejectIdentity() catch return error.WeakPublicKey;
310 }310 }
311 }311 }
312 var es: [count][2 * 32]i8 = undefined;312 var es: [count][2 * 32]i8 = undefined;
lib/std/crypto/aes.zig+3-3
...@@ -8,9 +8,9 @@ const std = @import("../std.zig");...@@ -8,9 +8,9 @@ const std = @import("../std.zig");
8const testing = std.testing;8const testing = std.testing;
9const builtin = std.builtin;9const builtin = std.builtin;
1010
11const has_aesni = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .aes);11const has_aesni = std.Target.x86.featureSetHas(std.Target.current.cpu.features, .aes);
12const has_avx = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .avx);12const has_avx = std.Target.x86.featureSetHas(std.Target.current.cpu.features, .avx);
13const has_armaes = comptime std.Target.aarch64.featureSetHas(std.Target.current.cpu.features, .aes);13const has_armaes = std.Target.aarch64.featureSetHas(std.Target.current.cpu.features, .aes);
14const impl = if (std.Target.current.cpu.arch == .x86_64 and has_aesni and has_avx) impl: {14const impl = if (std.Target.current.cpu.arch == .x86_64 and has_aesni and has_avx) impl: {
15 break :impl @import("aes/aesni.zig");15 break :impl @import("aes/aesni.zig");
16} else if (std.Target.current.cpu.arch == .aarch64 and has_armaes)16} else if (std.Target.current.cpu.arch == .aarch64 and has_armaes)
lib/std/crypto/aes_ocb.zig+2-2
...@@ -106,8 +106,8 @@ fn AesOcb(comptime Aes: anytype) type {...@@ -106,8 +106,8 @@ fn AesOcb(comptime Aes: anytype) type {
106 return offset;106 return offset;
107 }107 }
108108
109 const has_aesni = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .aes);109 const has_aesni = std.Target.x86.featureSetHas(std.Target.current.cpu.features, .aes);
110 const has_armaes = comptime std.Target.aarch64.featureSetHas(std.Target.current.cpu.features, .aes);110 const has_armaes = std.Target.aarch64.featureSetHas(std.Target.current.cpu.features, .aes);
111 const wb: usize = if ((std.Target.current.cpu.arch == .x86_64 and has_aesni) or (std.Target.current.cpu.arch == .aarch64 and has_armaes)) 4 else 0;111 const wb: usize = if ((std.Target.current.cpu.arch == .x86_64 and has_aesni) or (std.Target.current.cpu.arch == .aarch64 and has_armaes)) 4 else 0;
112112
113 /// c: ciphertext: output buffer should be of size m.len113 /// c: ciphertext: output buffer should be of size m.len
lib/std/crypto/ghash.zig+3-3
...@@ -137,9 +137,9 @@ pub const Ghash = struct {...@@ -137,9 +137,9 @@ pub const Ghash = struct {
137 return z0 | z1 | z2 | z3;137 return z0 | z1 | z2 | z3;
138 }138 }
139139
140 const has_pclmul = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .pclmul);140 const has_pclmul = std.Target.x86.featureSetHas(std.Target.current.cpu.features, .pclmul);
141 const has_avx = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .avx);141 const has_avx = std.Target.x86.featureSetHas(std.Target.current.cpu.features, .avx);
142 const has_armaes = comptime std.Target.aarch64.featureSetHas(std.Target.current.cpu.features, .aes);142 const has_armaes = std.Target.aarch64.featureSetHas(std.Target.current.cpu.features, .aes);
143 const clmul = if (std.Target.current.cpu.arch == .x86_64 and has_pclmul and has_avx) impl: {143 const clmul = if (std.Target.current.cpu.arch == .x86_64 and has_pclmul and has_avx) impl: {
144 break :impl clmul_pclmul;144 break :impl clmul_pclmul;
145 } else if (std.Target.current.cpu.arch == .aarch64 and has_armaes) impl: {145 } else if (std.Target.current.cpu.arch == .aarch64 and has_armaes) impl: {
lib/std/crypto/modes.zig+1-1
...@@ -16,7 +16,7 @@ const debug = std.debug;...@@ -16,7 +16,7 @@ const debug = std.debug;
16///16///
17/// Important: the counter mode doesn't provide authenticated encryption: the ciphertext can be trivially modified without this being detected.17/// Important: the counter mode doesn't provide authenticated encryption: the ciphertext can be trivially modified without this being detected.
18/// As a result, applications should generally never use it directly, but only in a construction that includes a MAC.18/// As a result, applications should generally never use it directly, but only in a construction that includes a MAC.
19pub fn ctr(comptime BlockCipher: anytype, block_cipher: BlockCipher, dst: []u8, src: []const u8, iv: [BlockCipher.block_length]u8, endian: comptime builtin.Endian) void {19pub fn ctr(comptime BlockCipher: anytype, block_cipher: BlockCipher, dst: []u8, src: []const u8, iv: [BlockCipher.block_length]u8, endian: builtin.Endian) void {
20 debug.assert(dst.len >= src.len);20 debug.assert(dst.len >= src.len);
21 const block_length = BlockCipher.block_length;21 const block_length = BlockCipher.block_length;
22 var counter: [BlockCipher.block_length]u8 = undefined;22 var counter: [BlockCipher.block_length]u8 = undefined;
lib/std/crypto/pcurves/common.zig+1-1
...@@ -43,7 +43,7 @@ pub fn Field(comptime params: FieldParams) type {...@@ -43,7 +43,7 @@ pub fn Field(comptime params: FieldParams) type {
43 pub const zero: Fe = Fe{ .limbs = mem.zeroes(Limbs) };43 pub const zero: Fe = Fe{ .limbs = mem.zeroes(Limbs) };
4444
45 /// One.45 /// One.
46 pub const one = comptime one: {46 pub const one = one: {
47 var fe: Fe = undefined;47 var fe: Fe = undefined;
48 fiat.setOne(&fe.limbs);48 fiat.setOne(&fe.limbs);
49 break :one fe;49 break :one fe;
lib/std/crypto/pcurves/p256.zig+5-5
...@@ -30,8 +30,8 @@ pub const P256 = struct {...@@ -30,8 +30,8 @@ pub const P256 = struct {
3030
31 /// The P256 base point.31 /// The P256 base point.
32 pub const basePoint = P256{32 pub const basePoint = P256{
33 .x = try Fe.fromInt(48439561293906451759052585252797914202762949526041747995844080717082404635286),33 .x = Fe.fromInt(48439561293906451759052585252797914202762949526041747995844080717082404635286) catch unreachable,
34 .y = try Fe.fromInt(36134250956749795798585127919587881956611106672985015071877198253568414405109),34 .y = Fe.fromInt(36134250956749795798585127919587881956611106672985015071877198253568414405109) catch unreachable,
35 .z = Fe.one,35 .z = Fe.one,
36 .is_base = true,36 .is_base = true,
37 };37 };
...@@ -39,7 +39,7 @@ pub const P256 = struct {...@@ -39,7 +39,7 @@ pub const P256 = struct {
39 /// The P256 neutral element.39 /// The P256 neutral element.
40 pub const identityElement = P256{ .x = Fe.zero, .y = Fe.one, .z = Fe.zero };40 pub const identityElement = P256{ .x = Fe.zero, .y = Fe.one, .z = Fe.zero };
4141
42 pub const B = try Fe.fromInt(41058363725152142129326129780047268409114441015993725554835256314039467401291);42 pub const B = Fe.fromInt(41058363725152142129326129780047268409114441015993725554835256314039467401291) catch unreachable;
4343
44 /// Reject the neutral element.44 /// Reject the neutral element.
45 pub fn rejectIdentity(p: P256) IdentityElementError!void {45 pub fn rejectIdentity(p: P256) IdentityElementError!void {
...@@ -390,12 +390,12 @@ pub const P256 = struct {...@@ -390,12 +390,12 @@ pub const P256 = struct {
390 return pc;390 return pc;
391 }391 }
392392
393 const basePointPc = comptime pc: {393 const basePointPc = pc: {
394 @setEvalBranchQuota(50000);394 @setEvalBranchQuota(50000);
395 break :pc precompute(P256.basePoint, 15);395 break :pc precompute(P256.basePoint, 15);
396 };396 };
397397
398 const basePointPc8 = comptime pc: {398 const basePointPc8 = pc: {
399 @setEvalBranchQuota(50000);399 @setEvalBranchQuota(50000);
400 break :pc precompute(P256.basePoint, 8);400 break :pc precompute(P256.basePoint, 8);
401 };401 };
lib/std/crypto/tlcsprng.zig+1-1
...@@ -111,7 +111,7 @@ fn tlsCsprngFill(_: *const std.rand.Random, buffer: []u8) void {...@@ -111,7 +111,7 @@ fn tlsCsprngFill(_: *const std.rand.Random, buffer: []u8) void {
111 wipe_mem.ptr,111 wipe_mem.ptr,
112 wipe_mem.len,112 wipe_mem.len,
113 os.MADV_WIPEONFORK,113 os.MADV_WIPEONFORK,
114 ) catch |_| {114 ) catch {
115 return initAndFill(buffer);115 return initAndFill(buffer);
116 };116 };
117 }117 }
lib/std/crypto/utils.zig+7-7
...@@ -20,9 +20,9 @@ pub fn timingSafeEql(comptime T: type, a: T, b: T) bool {...@@ -20,9 +20,9 @@ pub fn timingSafeEql(comptime T: type, a: T, b: T) bool {
20 for (a) |x, i| {20 for (a) |x, i| {
21 acc |= x ^ b[i];21 acc |= x ^ b[i];
22 }22 }
23 comptime const s = @typeInfo(C).Int.bits;23 const s = @typeInfo(C).Int.bits;
24 comptime const Cu = std.meta.Int(.unsigned, s);24 const Cu = std.meta.Int(.unsigned, s);
25 comptime const Cext = std.meta.Int(.unsigned, s + 1);25 const Cext = std.meta.Int(.unsigned, s + 1);
26 return @bitCast(bool, @truncate(u1, (@as(Cext, @bitCast(Cu, acc)) -% 1) >> s));26 return @bitCast(bool, @truncate(u1, (@as(Cext, @bitCast(Cu, acc)) -% 1) >> s));
27 },27 },
28 .Vector => |info| {28 .Vector => |info| {
...@@ -31,9 +31,9 @@ pub fn timingSafeEql(comptime T: type, a: T, b: T) bool {...@@ -31,9 +31,9 @@ pub fn timingSafeEql(comptime T: type, a: T, b: T) bool {
31 @compileError("Elements to be compared must be integers");31 @compileError("Elements to be compared must be integers");
32 }32 }
33 const acc = @reduce(.Or, a ^ b);33 const acc = @reduce(.Or, a ^ b);
34 comptime const s = @typeInfo(C).Int.bits;34 const s = @typeInfo(C).Int.bits;
35 comptime const Cu = std.meta.Int(.unsigned, s);35 const Cu = std.meta.Int(.unsigned, s);
36 comptime const Cext = std.meta.Int(.unsigned, s + 1);36 const Cext = std.meta.Int(.unsigned, s + 1);
37 return @bitCast(bool, @truncate(u1, (@as(Cext, @bitCast(Cu, acc)) -% 1) >> s));37 return @bitCast(bool, @truncate(u1, (@as(Cext, @bitCast(Cu, acc)) -% 1) >> s));
38 },38 },
39 else => {39 else => {
...@@ -50,7 +50,7 @@ pub fn timingSafeCompare(comptime T: type, a: []const T, b: []const T, endian: E...@@ -50,7 +50,7 @@ pub fn timingSafeCompare(comptime T: type, a: []const T, b: []const T, endian: E
50 .Int => |cinfo| if (cinfo.signedness != .unsigned) @compileError("Elements to be compared must be unsigned") else cinfo.bits,50 .Int => |cinfo| if (cinfo.signedness != .unsigned) @compileError("Elements to be compared must be unsigned") else cinfo.bits,
51 else => @compileError("Elements to be compared must be integers"),51 else => @compileError("Elements to be compared must be integers"),
52 };52 };
53 comptime const Cext = std.meta.Int(.unsigned, bits + 1);53 const Cext = std.meta.Int(.unsigned, bits + 1);
54 var gt: T = 0;54 var gt: T = 0;
55 var eq: T = 1;55 var eq: T = 1;
56 if (endian == .Little) {56 if (endian == .Little) {
lib/std/cstr.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std.zig");6const std = @import("std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const debug = std.debug;8const debug = std.debug;
9const mem = std.mem;9const mem = std.mem;
10const testing = std.testing;10const testing = std.testing;
lib/std/debug.zig+26-23
...@@ -21,6 +21,9 @@ const root = @import("root");...@@ -21,6 +21,9 @@ const root = @import("root");
21const maxInt = std.math.maxInt;21const maxInt = std.math.maxInt;
22const File = std.fs.File;22const File = std.fs.File;
23const windows = std.os.windows;23const windows = std.os.windows;
24const native_arch = std.Target.current.cpu.arch;
25const native_os = std.Target.current.os.tag;
26const native_endian = native_arch.endian();
2427
25pub const runtime_safety = switch (builtin.mode) {28pub const runtime_safety = switch (builtin.mode) {
26 .Debug, .ReleaseSafe => true,29 .Debug, .ReleaseSafe => true,
...@@ -90,7 +93,7 @@ pub fn detectTTYConfig() TTY.Config {...@@ -90,7 +93,7 @@ pub fn detectTTYConfig() TTY.Config {
90 const stderr_file = io.getStdErr();93 const stderr_file = io.getStdErr();
91 if (stderr_file.supportsAnsiEscapeCodes()) {94 if (stderr_file.supportsAnsiEscapeCodes()) {
92 return .escape_codes;95 return .escape_codes;
93 } else if (builtin.os.tag == .windows and stderr_file.isTty()) {96 } else if (native_os == .windows and stderr_file.isTty()) {
94 return .windows_api;97 return .windows_api;
95 } else {98 } else {
96 return .no_color;99 return .no_color;
...@@ -148,7 +151,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {...@@ -148,7 +151,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
148/// chopping off the irrelevant frames and shifting so that the returned addresses pointer151/// chopping off the irrelevant frames and shifting so that the returned addresses pointer
149/// equals the passed in addresses pointer.152/// equals the passed in addresses pointer.
150pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace) void {153pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace) void {
151 if (builtin.os.tag == .windows) {154 if (native_os == .windows) {
152 const addrs = stack_trace.instruction_addresses;155 const addrs = stack_trace.instruction_addresses;
153 const u32_addrs_len = @intCast(u32, addrs.len);156 const u32_addrs_len = @intCast(u32, addrs.len);
154 const first_addr = first_address orelse {157 const first_addr = first_address orelse {
...@@ -226,7 +229,7 @@ pub fn assert(ok: bool) void {...@@ -226,7 +229,7 @@ pub fn assert(ok: bool) void {
226pub fn panic(comptime format: []const u8, args: anytype) noreturn {229pub fn panic(comptime format: []const u8, args: anytype) noreturn {
227 @setCold(true);230 @setCold(true);
228 // TODO: remove conditional once wasi / LLVM defines __builtin_return_address231 // TODO: remove conditional once wasi / LLVM defines __builtin_return_address
229 const first_trace_addr = if (builtin.os.tag == .wasi) null else @returnAddress();232 const first_trace_addr = if (native_os == .wasi) null else @returnAddress();
230 panicExtra(null, first_trace_addr, format, args);233 panicExtra(null, first_trace_addr, format, args);
231}234}
232235
...@@ -337,7 +340,7 @@ pub const StackIterator = struct {...@@ -337,7 +340,7 @@ pub const StackIterator = struct {
337 fp: usize,340 fp: usize,
338341
339 pub fn init(first_address: ?usize, fp: ?usize) StackIterator {342 pub fn init(first_address: ?usize, fp: ?usize) StackIterator {
340 if (builtin.arch == .sparcv9) {343 if (native_arch == .sparcv9) {
341 // Flush all the register windows on stack.344 // Flush all the register windows on stack.
342 asm volatile (345 asm volatile (
343 \\ flushw346 \\ flushw
...@@ -351,25 +354,25 @@ pub const StackIterator = struct {...@@ -351,25 +354,25 @@ pub const StackIterator = struct {
351 }354 }
352355
353 // Offset of the saved BP wrt the frame pointer.356 // Offset of the saved BP wrt the frame pointer.
354 const fp_offset = if (comptime builtin.arch.isRISCV())357 const fp_offset = if (native_arch.isRISCV())
355 // On RISC-V the frame pointer points to the top of the saved register358 // On RISC-V the frame pointer points to the top of the saved register
356 // area, on pretty much every other architecture it points to the stack359 // area, on pretty much every other architecture it points to the stack
357 // slot where the previous frame pointer is saved.360 // slot where the previous frame pointer is saved.
358 2 * @sizeOf(usize)361 2 * @sizeOf(usize)
359 else if (comptime builtin.arch.isSPARC())362 else if (native_arch.isSPARC())
360 // On SPARC the previous frame pointer is stored at 14 slots past %fp+BIAS.363 // On SPARC the previous frame pointer is stored at 14 slots past %fp+BIAS.
361 14 * @sizeOf(usize)364 14 * @sizeOf(usize)
362 else365 else
363 0;366 0;
364367
365 const fp_bias = if (comptime builtin.arch.isSPARC())368 const fp_bias = if (native_arch.isSPARC())
366 // On SPARC frame pointers are biased by a constant.369 // On SPARC frame pointers are biased by a constant.
367 2047370 2047
368 else371 else
369 0;372 0;
370373
371 // Positive offset of the saved PC wrt the frame pointer.374 // Positive offset of the saved PC wrt the frame pointer.
372 const pc_offset = if (builtin.arch == .powerpc64le)375 const pc_offset = if (native_arch == .powerpc64le)
373 2 * @sizeOf(usize)376 2 * @sizeOf(usize)
374 else377 else
375 @sizeOf(usize);378 @sizeOf(usize);
...@@ -388,7 +391,7 @@ pub const StackIterator = struct {...@@ -388,7 +391,7 @@ pub const StackIterator = struct {
388 }391 }
389392
390 fn next_internal(self: *StackIterator) ?usize {393 fn next_internal(self: *StackIterator) ?usize {
391 const fp = if (comptime builtin.arch.isSPARC())394 const fp = if (comptime native_arch.isSPARC())
392 // On SPARC the offset is positive. (!)395 // On SPARC the offset is positive. (!)
393 math.add(usize, self.fp, fp_offset) catch return null396 math.add(usize, self.fp, fp_offset) catch return null
394 else397 else
...@@ -424,7 +427,7 @@ pub fn writeCurrentStackTrace(...@@ -424,7 +427,7 @@ pub fn writeCurrentStackTrace(
424 tty_config: TTY.Config,427 tty_config: TTY.Config,
425 start_addr: ?usize,428 start_addr: ?usize,
426) !void {429) !void {
427 if (builtin.os.tag == .windows) {430 if (native_os == .windows) {
428 return writeCurrentStackTraceWindows(out_stream, debug_info, tty_config, start_addr);431 return writeCurrentStackTraceWindows(out_stream, debug_info, tty_config, start_addr);
429 }432 }
430 var it = StackIterator.init(start_addr, null);433 var it = StackIterator.init(start_addr, null);
...@@ -482,7 +485,7 @@ pub const TTY = struct {...@@ -482,7 +485,7 @@ pub const TTY = struct {
482 .Bold => out_stream.writeAll(BOLD) catch return,485 .Bold => out_stream.writeAll(BOLD) catch return,
483 .Reset => out_stream.writeAll(RESET) catch return,486 .Reset => out_stream.writeAll(RESET) catch return,
484 },487 },
485 .windows_api => if (builtin.os.tag == .windows) {488 .windows_api => if (native_os == .windows) {
486 const stderr_file = io.getStdErr();489 const stderr_file = io.getStdErr();
487 const S = struct {490 const S = struct {
488 var attrs: windows.WORD = undefined;491 var attrs: windows.WORD = undefined;
...@@ -684,7 +687,7 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {...@@ -684,7 +687,7 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {
684 if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {687 if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {
685 return root.os.debug.openSelfDebugInfo(allocator);688 return root.os.debug.openSelfDebugInfo(allocator);
686 }689 }
687 switch (builtin.os.tag) {690 switch (native_os) {
688 .linux,691 .linux,
689 .freebsd,692 .freebsd,
690 .netbsd,693 .netbsd,
...@@ -897,7 +900,7 @@ pub fn readElfDebugInfo(allocator: *mem.Allocator, elf_file: File) !ModuleDebugI...@@ -897,7 +900,7 @@ pub fn readElfDebugInfo(allocator: *mem.Allocator, elf_file: File) !ModuleDebugI
897 elf.ELFDATA2MSB => .Big,900 elf.ELFDATA2MSB => .Big,
898 else => return error.InvalidElfEndian,901 else => return error.InvalidElfEndian,
899 };902 };
900 assert(endian == std.builtin.endian); // this is our own debug info903 assert(endian == native_endian); // this is our own debug info
901904
902 const shoff = hdr.e_shoff;905 const shoff = hdr.e_shoff;
903 const str_section_off = shoff + @as(u64, hdr.e_shentsize) * @as(u64, hdr.e_shstrndx);906 const str_section_off = shoff + @as(u64, hdr.e_shentsize) * @as(u64, hdr.e_shstrndx);
...@@ -1132,9 +1135,9 @@ pub const DebugInfo = struct {...@@ -1132,9 +1135,9 @@ pub const DebugInfo = struct {
1132 pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo {1135 pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
1133 if (comptime std.Target.current.isDarwin()) {1136 if (comptime std.Target.current.isDarwin()) {
1134 return self.lookupModuleDyld(address);1137 return self.lookupModuleDyld(address);
1135 } else if (builtin.os.tag == .windows) {1138 } else if (native_os == .windows) {
1136 return self.lookupModuleWin32(address);1139 return self.lookupModuleWin32(address);
1137 } else if (builtin.os.tag == .haiku) {1140 } else if (native_os == .haiku) {
1138 return self.lookupModuleHaiku(address);1141 return self.lookupModuleHaiku(address);
1139 } else {1142 } else {
1140 return self.lookupModuleDl(address);1143 return self.lookupModuleDl(address);
...@@ -1362,7 +1365,7 @@ const SymbolInfo = struct {...@@ -1362,7 +1365,7 @@ const SymbolInfo = struct {
1362 }1365 }
1363};1366};
13641367
1365pub const ModuleDebugInfo = switch (builtin.os.tag) {1368pub const ModuleDebugInfo = switch (native_os) {
1366 .macos, .ios, .watchos, .tvos => struct {1369 .macos, .ios, .watchos, .tvos => struct {
1367 base_address: usize,1370 base_address: usize,
1368 mapped_memory: []const u8,1371 mapped_memory: []const u8,
...@@ -1729,7 +1732,7 @@ fn getDebugInfoAllocator() *mem.Allocator {...@@ -1729,7 +1732,7 @@ fn getDebugInfoAllocator() *mem.Allocator {
1729}1732}
17301733
1731/// Whether or not the current target can print useful debug information when a segfault occurs.1734/// Whether or not the current target can print useful debug information when a segfault occurs.
1732pub const have_segfault_handling_support = switch (builtin.os.tag) {1735pub const have_segfault_handling_support = switch (native_os) {
1733 .linux, .netbsd => true,1736 .linux, .netbsd => true,
1734 .windows => true,1737 .windows => true,
1735 .freebsd, .openbsd => @hasDecl(os, "ucontext_t"),1738 .freebsd, .openbsd => @hasDecl(os, "ucontext_t"),
...@@ -1753,7 +1756,7 @@ pub fn attachSegfaultHandler() void {...@@ -1753,7 +1756,7 @@ pub fn attachSegfaultHandler() void {
1753 if (!have_segfault_handling_support) {1756 if (!have_segfault_handling_support) {
1754 @compileError("segfault handler not supported for this target");1757 @compileError("segfault handler not supported for this target");
1755 }1758 }
1756 if (builtin.os.tag == .windows) {1759 if (native_os == .windows) {
1757 windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);1760 windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
1758 return;1761 return;
1759 }1762 }
...@@ -1769,7 +1772,7 @@ pub fn attachSegfaultHandler() void {...@@ -1769,7 +1772,7 @@ pub fn attachSegfaultHandler() void {
1769}1772}
17701773
1771fn resetSegfaultHandler() void {1774fn resetSegfaultHandler() void {
1772 if (builtin.os.tag == .windows) {1775 if (native_os == .windows) {
1773 if (windows_segfault_handle) |handle| {1776 if (windows_segfault_handle) |handle| {
1774 assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0);1777 assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0);
1775 windows_segfault_handle = null;1778 windows_segfault_handle = null;
...@@ -1792,7 +1795,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v...@@ -1792,7 +1795,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v
1792 // and the resulting segfault will crash the process rather than continually dump stack traces.1795 // and the resulting segfault will crash the process rather than continually dump stack traces.
1793 resetSegfaultHandler();1796 resetSegfaultHandler();
17941797
1795 const addr = switch (builtin.os.tag) {1798 const addr = switch (native_os) {
1796 .linux => @ptrToInt(info.fields.sigfault.addr),1799 .linux => @ptrToInt(info.fields.sigfault.addr),
1797 .freebsd => @ptrToInt(info.addr),1800 .freebsd => @ptrToInt(info.addr),
1798 .netbsd => @ptrToInt(info.info.reason.fault.addr),1801 .netbsd => @ptrToInt(info.info.reason.fault.addr),
...@@ -1811,7 +1814,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v...@@ -1811,7 +1814,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v
1811 } catch os.abort();1814 } catch os.abort();
1812 }1815 }
18131816
1814 switch (builtin.arch) {1817 switch (native_arch) {
1815 .i386 => {1818 .i386 => {
1816 const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));1819 const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
1817 const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_EIP]);1820 const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_EIP]);
...@@ -1820,13 +1823,13 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v...@@ -1820,13 +1823,13 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v
1820 },1823 },
1821 .x86_64 => {1824 .x86_64 => {
1822 const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));1825 const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
1823 const ip = switch (builtin.os.tag) {1826 const ip = switch (native_os) {
1824 .linux, .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]),1827 .linux, .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]),
1825 .freebsd => @intCast(usize, ctx.mcontext.rip),1828 .freebsd => @intCast(usize, ctx.mcontext.rip),
1826 .openbsd => @intCast(usize, ctx.sc_rip),1829 .openbsd => @intCast(usize, ctx.sc_rip),
1827 else => unreachable,1830 else => unreachable,
1828 };1831 };
1829 const bp = switch (builtin.os.tag) {1832 const bp = switch (native_os) {
1830 .linux, .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG_RBP]),1833 .linux, .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG_RBP]),
1831 .openbsd => @intCast(usize, ctx.sc_rbp),1834 .openbsd => @intCast(usize, ctx.sc_rbp),
1832 .freebsd => @intCast(usize, ctx.mcontext.rbp),1835 .freebsd => @intCast(usize, ctx.mcontext.rbp),
lib/std/dwarf.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std.zig");6const std = @import("std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const debug = std.debug;8const debug = std.debug;
9const fs = std.fs;9const fs = std.fs;
10const io = std.io;10const io = std.io;
lib/std/dynamic_library.zig+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");6const builtin = std.builtin;
77
8const std = @import("std.zig");8const std = @import("std.zig");
9const mem = std.mem;9const mem = std.mem;
lib/std/elf.zig+9-9
...@@ -4,13 +4,13 @@...@@ -4,13 +4,13 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std.zig");6const std = @import("std.zig");
7const builtin = std.builtin;
8const io = std.io;7const io = std.io;
9const os = std.os;8const os = std.os;
10const math = std.math;9const math = std.math;
11const mem = std.mem;10const mem = std.mem;
12const debug = std.debug;11const debug = std.debug;
13const File = std.fs.File;12const File = std.fs.File;
13const native_endian = @import("builtin").target.cpu.arch.endian();
1414
15pub const AT_NULL = 0;15pub const AT_NULL = 0;
16pub const AT_IGNORE = 1;16pub const AT_IGNORE = 1;
...@@ -311,7 +311,7 @@ pub const VER_FLG_BASE = 0x1;...@@ -311,7 +311,7 @@ pub const VER_FLG_BASE = 0x1;
311pub const VER_FLG_WEAK = 0x2;311pub const VER_FLG_WEAK = 0x2;
312312
313/// File types313/// File types
314pub const ET = extern enum(u16) {314pub const ET = enum(u16) {
315 /// No file type315 /// No file type
316 NONE = 0,316 NONE = 0,
317317
...@@ -336,7 +336,7 @@ pub const ET = extern enum(u16) {...@@ -336,7 +336,7 @@ pub const ET = extern enum(u16) {
336336
337/// All integers are native endian.337/// All integers are native endian.
338pub const Header = struct {338pub const Header = struct {
339 endian: builtin.Endian,339 endian: std.builtin.Endian,
340 machine: EM,340 machine: EM,
341 is_64: bool,341 is_64: bool,
342 entry: u64,342 entry: u64,
...@@ -380,7 +380,7 @@ pub const Header = struct {...@@ -380,7 +380,7 @@ pub const Header = struct {
380 ELFDATA2MSB => .Big,380 ELFDATA2MSB => .Big,
381 else => return error.InvalidElfEndian,381 else => return error.InvalidElfEndian,
382 };382 };
383 const need_bswap = endian != std.builtin.endian;383 const need_bswap = endian != native_endian;
384384
385 const is_64 = switch (hdr32.e_ident[EI_CLASS]) {385 const is_64 = switch (hdr32.e_ident[EI_CLASS]) {
386 ELFCLASS32 => false,386 ELFCLASS32 => false,
...@@ -426,7 +426,7 @@ pub fn ProgramHeaderIterator(ParseSource: anytype) type {...@@ -426,7 +426,7 @@ pub fn ProgramHeaderIterator(ParseSource: anytype) type {
426 try self.parse_source.reader().readNoEof(mem.asBytes(&phdr));426 try self.parse_source.reader().readNoEof(mem.asBytes(&phdr));
427427
428 // ELF endianness matches native endianness.428 // ELF endianness matches native endianness.
429 if (self.elf_header.endian == std.builtin.endian) return phdr;429 if (self.elf_header.endian == native_endian) return phdr;
430430
431 // Convert fields to native endianness.431 // Convert fields to native endianness.
432 bswapAllFields(Elf64_Phdr, &phdr);432 bswapAllFields(Elf64_Phdr, &phdr);
...@@ -439,7 +439,7 @@ pub fn ProgramHeaderIterator(ParseSource: anytype) type {...@@ -439,7 +439,7 @@ pub fn ProgramHeaderIterator(ParseSource: anytype) type {
439 try self.parse_source.reader().readNoEof(mem.asBytes(&phdr));439 try self.parse_source.reader().readNoEof(mem.asBytes(&phdr));
440440
441 // ELF endianness does NOT match native endianness.441 // ELF endianness does NOT match native endianness.
442 if (self.elf_header.endian != std.builtin.endian) {442 if (self.elf_header.endian != native_endian) {
443 // Convert fields to native endianness.443 // Convert fields to native endianness.
444 bswapAllFields(Elf32_Phdr, &phdr);444 bswapAllFields(Elf32_Phdr, &phdr);
445 }445 }
...@@ -476,7 +476,7 @@ pub fn SectionHeaderIterator(ParseSource: anytype) type {...@@ -476,7 +476,7 @@ pub fn SectionHeaderIterator(ParseSource: anytype) type {
476 try self.parse_source.reader().readNoEof(mem.asBytes(&shdr));476 try self.parse_source.reader().readNoEof(mem.asBytes(&shdr));
477477
478 // ELF endianness matches native endianness.478 // ELF endianness matches native endianness.
479 if (self.elf_header.endian == std.builtin.endian) return shdr;479 if (self.elf_header.endian == native_endian) return shdr;
480480
481 // Convert fields to native endianness.481 // Convert fields to native endianness.
482 return Elf64_Shdr{482 return Elf64_Shdr{
...@@ -499,7 +499,7 @@ pub fn SectionHeaderIterator(ParseSource: anytype) type {...@@ -499,7 +499,7 @@ pub fn SectionHeaderIterator(ParseSource: anytype) type {
499 try self.parse_source.reader().readNoEof(mem.asBytes(&shdr));499 try self.parse_source.reader().readNoEof(mem.asBytes(&shdr));
500500
501 // ELF endianness does NOT match native endianness.501 // ELF endianness does NOT match native endianness.
502 if (self.elf_header.endian != std.builtin.endian) {502 if (self.elf_header.endian != native_endian) {
503 // Convert fields to native endianness.503 // Convert fields to native endianness.
504 shdr = .{504 shdr = .{
505 .sh_name = @byteSwap(@TypeOf(shdr.sh_name), shdr.sh_name),505 .sh_name = @byteSwap(@TypeOf(shdr.sh_name), shdr.sh_name),
...@@ -991,7 +991,7 @@ pub const Half = switch (@sizeOf(usize)) {...@@ -991,7 +991,7 @@ pub const Half = switch (@sizeOf(usize)) {
991/// See current registered ELF machine architectures at:991/// See current registered ELF machine architectures at:
992/// http://www.uxsglobal.com/developers/gabi/latest/ch4.eheader.html992/// http://www.uxsglobal.com/developers/gabi/latest/ch4.eheader.html
993/// The underscore prefix is because many of these start with numbers.993/// The underscore prefix is because many of these start with numbers.
994pub const EM = extern enum(u16) {994pub const EM = enum(u16) {
995 /// No machine995 /// No machine
996 _NONE = 0,996 _NONE = 0,
997997
lib/std/enums.zig+12-448
...@@ -18,7 +18,7 @@ const EnumField = std.builtin.TypeInfo.EnumField;...@@ -18,7 +18,7 @@ const EnumField = std.builtin.TypeInfo.EnumField;
18pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type {18pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type {
19 const StructField = std.builtin.TypeInfo.StructField;19 const StructField = std.builtin.TypeInfo.StructField;
20 var fields: []const StructField = &[_]StructField{};20 var fields: []const StructField = &[_]StructField{};
21 for (uniqueFields(E)) |field, i| {21 for (std.meta.fields(E)) |field, i| {
22 fields = fields ++ &[_]StructField{.{22 fields = fields ++ &[_]StructField{.{
23 .name = field.name,23 .name = field.name,
24 .field_type = Data,24 .field_type = Data,
...@@ -48,72 +48,12 @@ pub fn valuesFromFields(comptime E: type, comptime fields: []const EnumField) []...@@ -48,72 +48,12 @@ pub fn valuesFromFields(comptime E: type, comptime fields: []const EnumField) []
48 }48 }
49}49}
5050
51test "std.enums.valuesFromFields" {
52 const E = extern enum { a, b, c, d = 0 };
53 const fields = valuesFromFields(E, &[_]EnumField{
54 .{ .name = "b", .value = undefined },
55 .{ .name = "a", .value = undefined },
56 .{ .name = "a", .value = undefined },
57 .{ .name = "d", .value = undefined },
58 });
59 try testing.expectEqual(E.b, fields[0]);
60 try testing.expectEqual(E.a, fields[1]);
61 try testing.expectEqual(E.d, fields[2]); // a == d
62 try testing.expectEqual(E.d, fields[3]);
63}
64
65/// Returns the set of all named values in the given enum, in51/// Returns the set of all named values in the given enum, in
66/// declaration order.52/// declaration order.
67pub fn values(comptime E: type) []const E {53pub fn values(comptime E: type) []const E {
68 return comptime valuesFromFields(E, @typeInfo(E).Enum.fields);54 return comptime valuesFromFields(E, @typeInfo(E).Enum.fields);
69}55}
7056
71test "std.enum.values" {
72 const E = extern enum { a, b, c, d = 0 };
73 try testing.expectEqualSlices(E, &.{ .a, .b, .c, .d }, values(E));
74}
75
76/// Returns the set of all unique named values in the given enum, in
77/// declaration order. For repeated values in extern enums, only the
78/// first name for each value is included.
79pub fn uniqueValues(comptime E: type) []const E {
80 return comptime valuesFromFields(E, uniqueFields(E));
81}
82
83test "std.enum.uniqueValues" {
84 const E = extern enum { a, b, c, d = 0, e, f = 3 };
85 try testing.expectEqualSlices(E, &.{ .a, .b, .c, .f }, uniqueValues(E));
86
87 const F = enum { a, b, c };
88 try testing.expectEqualSlices(F, &.{ .a, .b, .c }, uniqueValues(F));
89}
90
91/// Returns the set of all unique field values in the given enum, in
92/// declaration order. For repeated values in extern enums, only the
93/// first name for each value is included.
94pub fn uniqueFields(comptime E: type) []const EnumField {
95 comptime {
96 const info = @typeInfo(E).Enum;
97 const raw_fields = info.fields;
98 // Only extern enums can contain duplicates,
99 // so fast path other types.
100 if (info.layout != .Extern) {
101 return raw_fields;
102 }
103
104 var unique_fields: []const EnumField = &[_]EnumField{};
105 outer: for (raw_fields) |candidate| {
106 for (unique_fields) |u| {
107 if (u.value == candidate.value)
108 continue :outer;
109 }
110 unique_fields = unique_fields ++ &[_]EnumField{candidate};
111 }
112
113 return unique_fields;
114 }
115}
116
117/// Determines the length of a direct-mapped enum array, indexed by57/// Determines the length of a direct-mapped enum array, indexed by
118/// @intCast(usize, @enumToInt(enum_value)).58/// @intCast(usize, @enumToInt(enum_value)).
119/// If the enum is non-exhaustive, the resulting length will only be enough59/// If the enum is non-exhaustive, the resulting length will only be enough
...@@ -126,7 +66,7 @@ pub fn uniqueFields(comptime E: type) []const EnumField {...@@ -126,7 +66,7 @@ pub fn uniqueFields(comptime E: type) []const EnumField {
126fn directEnumArrayLen(comptime E: type, comptime max_unused_slots: comptime_int) comptime_int {66fn directEnumArrayLen(comptime E: type, comptime max_unused_slots: comptime_int) comptime_int {
127 var max_value: comptime_int = -1;67 var max_value: comptime_int = -1;
128 const max_usize: comptime_int = ~@as(usize, 0);68 const max_usize: comptime_int = ~@as(usize, 0);
129 const fields = uniqueFields(E);69 const fields = std.meta.fields(E);
130 for (fields) |f| {70 for (fields) |f| {
131 if (f.value < 0) {71 if (f.value < 0) {
132 @compileError("Cannot create a direct enum array for " ++ @typeName(E) ++ ", field ." ++ f.name ++ " has a negative value.");72 @compileError("Cannot create a direct enum array for " ++ @typeName(E) ++ ", field ." ++ f.name ++ " has a negative value.");
...@@ -248,8 +188,8 @@ pub fn nameCast(comptime E: type, comptime value: anytype) E {...@@ -248,8 +188,8 @@ pub fn nameCast(comptime E: type, comptime value: anytype) E {
248}188}
249189
250test "std.enums.nameCast" {190test "std.enums.nameCast" {
251 const A = enum { a = 0, b = 1 };191 const A = enum(u1) { a = 0, b = 1 };
252 const B = enum { a = 1, b = 0 };192 const B = enum(u1) { a = 1, b = 0 };
253 try testing.expectEqual(A.a, nameCast(A, .a));193 try testing.expectEqual(A.a, nameCast(A, .a));
254 try testing.expectEqual(A.a, nameCast(A, A.a));194 try testing.expectEqual(A.a, nameCast(A, A.a));
255 try testing.expectEqual(A.a, nameCast(A, B.a));195 try testing.expectEqual(A.a, nameCast(A, B.a));
...@@ -283,8 +223,8 @@ pub fn EnumSet(comptime E: type) type {...@@ -283,8 +223,8 @@ pub fn EnumSet(comptime E: type) type {
283 var result = Self{};223 var result = Self{};
284 comptime var i: usize = 0;224 comptime var i: usize = 0;
285 inline while (i < Self.len) : (i += 1) {225 inline while (i < Self.len) : (i += 1) {
286 comptime const key = Indexer.keyForIndex(i);226 const key = comptime Indexer.keyForIndex(i);
287 comptime const tag = @tagName(key);227 const tag = comptime @tagName(key);
288 if (@field(init_values, tag)) {228 if (@field(init_values, tag)) {
289 result.bits.set(i);229 result.bits.set(i);
290 }230 }
...@@ -311,8 +251,8 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {...@@ -311,8 +251,8 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {
311 var result = Self{};251 var result = Self{};
312 comptime var i: usize = 0;252 comptime var i: usize = 0;
313 inline while (i < Self.len) : (i += 1) {253 inline while (i < Self.len) : (i += 1) {
314 comptime const key = Indexer.keyForIndex(i);254 const key = comptime Indexer.keyForIndex(i);
315 comptime const tag = @tagName(key);255 const tag = comptime @tagName(key);
316 if (@field(init_values, tag)) |*v| {256 if (@field(init_values, tag)) |*v| {
317 result.bits.set(i);257 result.bits.set(i);
318 result.values[i] = v.*;258 result.values[i] = v.*;
...@@ -344,8 +284,8 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {...@@ -344,8 +284,8 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {
344 };284 };
345 comptime var i: usize = 0;285 comptime var i: usize = 0;
346 inline while (i < Self.len) : (i += 1) {286 inline while (i < Self.len) : (i += 1) {
347 comptime const key = Indexer.keyForIndex(i);287 const key = comptime Indexer.keyForIndex(i);
348 comptime const tag = @tagName(key);288 const tag = comptime @tagName(key);
349 result.values[i] = @field(init_values, tag);289 result.values[i] = @field(init_values, tag);
350 }290 }
351 return result;291 return result;
...@@ -796,7 +736,7 @@ pub fn EnumIndexer(comptime E: type) type {...@@ -796,7 +736,7 @@ pub fn EnumIndexer(comptime E: type) type {
796 @compileError("Cannot create an enum indexer for a non-exhaustive enum.");736 @compileError("Cannot create an enum indexer for a non-exhaustive enum.");
797 }737 }
798738
799 const const_fields = uniqueFields(E);739 const const_fields = std.meta.fields(E);
800 var fields = const_fields[0..const_fields.len].*;740 var fields = const_fields[0..const_fields.len].*;
801 if (fields.len == 0) {741 if (fields.len == 0) {
802 return struct {742 return struct {
...@@ -848,7 +788,7 @@ pub fn EnumIndexer(comptime E: type) type {...@@ -848,7 +788,7 @@ pub fn EnumIndexer(comptime E: type) type {
848}788}
849789
850test "std.enums.EnumIndexer dense zeroed" {790test "std.enums.EnumIndexer dense zeroed" {
851 const E = enum { b = 1, a = 0, c = 2 };791 const E = enum(u2) { b = 1, a = 0, c = 2 };
852 const Indexer = EnumIndexer(E);792 const Indexer = EnumIndexer(E);
853 ensureIndexer(Indexer);793 ensureIndexer(Indexer);
854 try testing.expectEqual(E, Indexer.Key);794 try testing.expectEqual(E, Indexer.Key);
...@@ -910,379 +850,3 @@ test "std.enums.EnumIndexer sparse" {...@@ -910,379 +850,3 @@ test "std.enums.EnumIndexer sparse" {
910 try testing.expectEqual(E.b, Indexer.keyForIndex(1));850 try testing.expectEqual(E.b, Indexer.keyForIndex(1));
911 try testing.expectEqual(E.c, Indexer.keyForIndex(2));851 try testing.expectEqual(E.c, Indexer.keyForIndex(2));
912}852}
913
914test "std.enums.EnumIndexer repeats" {
915 const E = extern enum { a = -2, c = 6, b = 4, b2 = 4 };
916 const Indexer = EnumIndexer(E);
917 ensureIndexer(Indexer);
918 try testing.expectEqual(E, Indexer.Key);
919 try testing.expectEqual(@as(usize, 3), Indexer.count);
920
921 try testing.expectEqual(@as(usize, 0), Indexer.indexOf(.a));
922 try testing.expectEqual(@as(usize, 1), Indexer.indexOf(.b));
923 try testing.expectEqual(@as(usize, 2), Indexer.indexOf(.c));
924
925 try testing.expectEqual(E.a, Indexer.keyForIndex(0));
926 try testing.expectEqual(E.b, Indexer.keyForIndex(1));
927 try testing.expectEqual(E.c, Indexer.keyForIndex(2));
928}
929
930test "std.enums.EnumSet" {
931 const E = extern enum { a, b, c, d, e = 0 };
932 const Set = EnumSet(E);
933 try testing.expectEqual(E, Set.Key);
934 try testing.expectEqual(EnumIndexer(E), Set.Indexer);
935 try testing.expectEqual(@as(usize, 4), Set.len);
936
937 // Empty sets
938 const empty = Set{};
939 comptime try testing.expect(empty.count() == 0);
940
941 var empty_b = Set.init(.{});
942 try testing.expect(empty_b.count() == 0);
943
944 const empty_c = comptime Set.init(.{});
945 comptime try testing.expect(empty_c.count() == 0);
946
947 const full = Set.initFull();
948 try testing.expect(full.count() == Set.len);
949
950 const full_b = comptime Set.initFull();
951 comptime try testing.expect(full_b.count() == Set.len);
952
953 try testing.expectEqual(false, empty.contains(.a));
954 try testing.expectEqual(false, empty.contains(.b));
955 try testing.expectEqual(false, empty.contains(.c));
956 try testing.expectEqual(false, empty.contains(.d));
957 try testing.expectEqual(false, empty.contains(.e));
958 {
959 var iter = empty_b.iterator();
960 try testing.expectEqual(@as(?E, null), iter.next());
961 }
962
963 var mut = Set.init(.{
964 .a = true,
965 .c = true,
966 });
967 try testing.expectEqual(@as(usize, 2), mut.count());
968 try testing.expectEqual(true, mut.contains(.a));
969 try testing.expectEqual(false, mut.contains(.b));
970 try testing.expectEqual(true, mut.contains(.c));
971 try testing.expectEqual(false, mut.contains(.d));
972 try testing.expectEqual(true, mut.contains(.e)); // aliases a
973 {
974 var it = mut.iterator();
975 try testing.expectEqual(@as(?E, .a), it.next());
976 try testing.expectEqual(@as(?E, .c), it.next());
977 try testing.expectEqual(@as(?E, null), it.next());
978 }
979
980 mut.toggleAll();
981 try testing.expectEqual(@as(usize, 2), mut.count());
982 try testing.expectEqual(false, mut.contains(.a));
983 try testing.expectEqual(true, mut.contains(.b));
984 try testing.expectEqual(false, mut.contains(.c));
985 try testing.expectEqual(true, mut.contains(.d));
986 try testing.expectEqual(false, mut.contains(.e)); // aliases a
987 {
988 var it = mut.iterator();
989 try testing.expectEqual(@as(?E, .b), it.next());
990 try testing.expectEqual(@as(?E, .d), it.next());
991 try testing.expectEqual(@as(?E, null), it.next());
992 }
993
994 mut.toggleSet(Set.init(.{ .a = true, .b = true }));
995 try testing.expectEqual(@as(usize, 2), mut.count());
996 try testing.expectEqual(true, mut.contains(.a));
997 try testing.expectEqual(false, mut.contains(.b));
998 try testing.expectEqual(false, mut.contains(.c));
999 try testing.expectEqual(true, mut.contains(.d));
1000 try testing.expectEqual(true, mut.contains(.e)); // aliases a
1001
1002 mut.setUnion(Set.init(.{ .a = true, .b = true }));
1003 try testing.expectEqual(@as(usize, 3), mut.count());
1004 try testing.expectEqual(true, mut.contains(.a));
1005 try testing.expectEqual(true, mut.contains(.b));
1006 try testing.expectEqual(false, mut.contains(.c));
1007 try testing.expectEqual(true, mut.contains(.d));
1008
1009 mut.remove(.c);
1010 mut.remove(.b);
1011 try testing.expectEqual(@as(usize, 2), mut.count());
1012 try testing.expectEqual(true, mut.contains(.a));
1013 try testing.expectEqual(false, mut.contains(.b));
1014 try testing.expectEqual(false, mut.contains(.c));
1015 try testing.expectEqual(true, mut.contains(.d));
1016
1017 mut.setIntersection(Set.init(.{ .a = true, .b = true }));
1018 try testing.expectEqual(@as(usize, 1), mut.count());
1019 try testing.expectEqual(true, mut.contains(.a));
1020 try testing.expectEqual(false, mut.contains(.b));
1021 try testing.expectEqual(false, mut.contains(.c));
1022 try testing.expectEqual(false, mut.contains(.d));
1023
1024 mut.insert(.a);
1025 mut.insert(.b);
1026 try testing.expectEqual(@as(usize, 2), mut.count());
1027 try testing.expectEqual(true, mut.contains(.a));
1028 try testing.expectEqual(true, mut.contains(.b));
1029 try testing.expectEqual(false, mut.contains(.c));
1030 try testing.expectEqual(false, mut.contains(.d));
1031
1032 mut.setPresent(.a, false);
1033 mut.toggle(.b);
1034 mut.toggle(.c);
1035 mut.setPresent(.d, true);
1036 try testing.expectEqual(@as(usize, 2), mut.count());
1037 try testing.expectEqual(false, mut.contains(.a));
1038 try testing.expectEqual(false, mut.contains(.b));
1039 try testing.expectEqual(true, mut.contains(.c));
1040 try testing.expectEqual(true, mut.contains(.d));
1041}
1042
1043test "std.enums.EnumArray void" {
1044 const E = extern enum { a, b, c, d, e = 0 };
1045 const ArrayVoid = EnumArray(E, void);
1046 try testing.expectEqual(E, ArrayVoid.Key);
1047 try testing.expectEqual(EnumIndexer(E), ArrayVoid.Indexer);
1048 try testing.expectEqual(void, ArrayVoid.Value);
1049 try testing.expectEqual(@as(usize, 4), ArrayVoid.len);
1050
1051 const undef = ArrayVoid.initUndefined();
1052 var inst = ArrayVoid.initFill({});
1053 const inst2 = ArrayVoid.init(.{ .a = {}, .b = {}, .c = {}, .d = {} });
1054 const inst3 = ArrayVoid.initDefault({}, .{});
1055
1056 _ = inst.get(.a);
1057 _ = inst.getPtr(.b);
1058 _ = inst.getPtrConst(.c);
1059 inst.set(.a, {});
1060
1061 var it = inst.iterator();
1062 try testing.expectEqual(E.a, it.next().?.key);
1063 try testing.expectEqual(E.b, it.next().?.key);
1064 try testing.expectEqual(E.c, it.next().?.key);
1065 try testing.expectEqual(E.d, it.next().?.key);
1066 try testing.expect(it.next() == null);
1067}
1068
1069test "std.enums.EnumArray sized" {
1070 const E = extern enum { a, b, c, d, e = 0 };
1071 const Array = EnumArray(E, usize);
1072 try testing.expectEqual(E, Array.Key);
1073 try testing.expectEqual(EnumIndexer(E), Array.Indexer);
1074 try testing.expectEqual(usize, Array.Value);
1075 try testing.expectEqual(@as(usize, 4), Array.len);
1076
1077 const undef = Array.initUndefined();
1078 var inst = Array.initFill(5);
1079 const inst2 = Array.init(.{ .a = 1, .b = 2, .c = 3, .d = 4 });
1080 const inst3 = Array.initDefault(6, .{ .b = 4, .c = 2 });
1081
1082 try testing.expectEqual(@as(usize, 5), inst.get(.a));
1083 try testing.expectEqual(@as(usize, 5), inst.get(.b));
1084 try testing.expectEqual(@as(usize, 5), inst.get(.c));
1085 try testing.expectEqual(@as(usize, 5), inst.get(.d));
1086
1087 try testing.expectEqual(@as(usize, 1), inst2.get(.a));
1088 try testing.expectEqual(@as(usize, 2), inst2.get(.b));
1089 try testing.expectEqual(@as(usize, 3), inst2.get(.c));
1090 try testing.expectEqual(@as(usize, 4), inst2.get(.d));
1091
1092 try testing.expectEqual(@as(usize, 6), inst3.get(.a));
1093 try testing.expectEqual(@as(usize, 4), inst3.get(.b));
1094 try testing.expectEqual(@as(usize, 2), inst3.get(.c));
1095 try testing.expectEqual(@as(usize, 6), inst3.get(.d));
1096
1097 try testing.expectEqual(&inst.values[0], inst.getPtr(.a));
1098 try testing.expectEqual(&inst.values[1], inst.getPtr(.b));
1099 try testing.expectEqual(&inst.values[2], inst.getPtr(.c));
1100 try testing.expectEqual(&inst.values[3], inst.getPtr(.d));
1101
1102 try testing.expectEqual(@as(*const usize, &inst.values[0]), inst.getPtrConst(.a));
1103 try testing.expectEqual(@as(*const usize, &inst.values[1]), inst.getPtrConst(.b));
1104 try testing.expectEqual(@as(*const usize, &inst.values[2]), inst.getPtrConst(.c));
1105 try testing.expectEqual(@as(*const usize, &inst.values[3]), inst.getPtrConst(.d));
1106
1107 inst.set(.c, 8);
1108 try testing.expectEqual(@as(usize, 5), inst.get(.a));
1109 try testing.expectEqual(@as(usize, 5), inst.get(.b));
1110 try testing.expectEqual(@as(usize, 8), inst.get(.c));
1111 try testing.expectEqual(@as(usize, 5), inst.get(.d));
1112
1113 var it = inst.iterator();
1114 const Entry = Array.Entry;
1115 try testing.expectEqual(@as(?Entry, Entry{
1116 .key = .a,
1117 .value = &inst.values[0],
1118 }), it.next());
1119 try testing.expectEqual(@as(?Entry, Entry{
1120 .key = .b,
1121 .value = &inst.values[1],
1122 }), it.next());
1123 try testing.expectEqual(@as(?Entry, Entry{
1124 .key = .c,
1125 .value = &inst.values[2],
1126 }), it.next());
1127 try testing.expectEqual(@as(?Entry, Entry{
1128 .key = .d,
1129 .value = &inst.values[3],
1130 }), it.next());
1131 try testing.expectEqual(@as(?Entry, null), it.next());
1132}
1133
1134test "std.enums.EnumMap void" {
1135 const E = extern enum { a, b, c, d, e = 0 };
1136 const Map = EnumMap(E, void);
1137 try testing.expectEqual(E, Map.Key);
1138 try testing.expectEqual(EnumIndexer(E), Map.Indexer);
1139 try testing.expectEqual(void, Map.Value);
1140 try testing.expectEqual(@as(usize, 4), Map.len);
1141
1142 const b = Map.initFull({});
1143 try testing.expectEqual(@as(usize, 4), b.count());
1144
1145 const c = Map.initFullWith(.{ .a = {}, .b = {}, .c = {}, .d = {} });
1146 try testing.expectEqual(@as(usize, 4), c.count());
1147
1148 const d = Map.initFullWithDefault({}, .{ .b = {} });
1149 try testing.expectEqual(@as(usize, 4), d.count());
1150
1151 var a = Map.init(.{ .b = {}, .d = {} });
1152 try testing.expectEqual(@as(usize, 2), a.count());
1153 try testing.expectEqual(false, a.contains(.a));
1154 try testing.expectEqual(true, a.contains(.b));
1155 try testing.expectEqual(false, a.contains(.c));
1156 try testing.expectEqual(true, a.contains(.d));
1157 try testing.expect(a.get(.a) == null);
1158 try testing.expect(a.get(.b) != null);
1159 try testing.expect(a.get(.c) == null);
1160 try testing.expect(a.get(.d) != null);
1161 try testing.expect(a.getPtr(.a) == null);
1162 try testing.expect(a.getPtr(.b) != null);
1163 try testing.expect(a.getPtr(.c) == null);
1164 try testing.expect(a.getPtr(.d) != null);
1165 try testing.expect(a.getPtrConst(.a) == null);
1166 try testing.expect(a.getPtrConst(.b) != null);
1167 try testing.expect(a.getPtrConst(.c) == null);
1168 try testing.expect(a.getPtrConst(.d) != null);
1169 _ = a.getPtrAssertContains(.b);
1170 _ = a.getAssertContains(.d);
1171
1172 a.put(.a, {});
1173 a.put(.a, {});
1174 a.putUninitialized(.c).* = {};
1175 a.putUninitialized(.c).* = {};
1176
1177 try testing.expectEqual(@as(usize, 4), a.count());
1178 try testing.expect(a.get(.a) != null);
1179 try testing.expect(a.get(.b) != null);
1180 try testing.expect(a.get(.c) != null);
1181 try testing.expect(a.get(.d) != null);
1182
1183 a.remove(.a);
1184 _ = a.fetchRemove(.c);
1185
1186 var iter = a.iterator();
1187 const Entry = Map.Entry;
1188 try testing.expectEqual(E.b, iter.next().?.key);
1189 try testing.expectEqual(E.d, iter.next().?.key);
1190 try testing.expect(iter.next() == null);
1191}
1192
1193test "std.enums.EnumMap sized" {
1194 const E = extern enum { a, b, c, d, e = 0 };
1195 const Map = EnumMap(E, usize);
1196 try testing.expectEqual(E, Map.Key);
1197 try testing.expectEqual(EnumIndexer(E), Map.Indexer);
1198 try testing.expectEqual(usize, Map.Value);
1199 try testing.expectEqual(@as(usize, 4), Map.len);
1200
1201 const b = Map.initFull(5);
1202 try testing.expectEqual(@as(usize, 4), b.count());
1203 try testing.expect(b.contains(.a));
1204 try testing.expect(b.contains(.b));
1205 try testing.expect(b.contains(.c));
1206 try testing.expect(b.contains(.d));
1207 try testing.expectEqual(@as(?usize, 5), b.get(.a));
1208 try testing.expectEqual(@as(?usize, 5), b.get(.b));
1209 try testing.expectEqual(@as(?usize, 5), b.get(.c));
1210 try testing.expectEqual(@as(?usize, 5), b.get(.d));
1211
1212 const c = Map.initFullWith(.{ .a = 1, .b = 2, .c = 3, .d = 4 });
1213 try testing.expectEqual(@as(usize, 4), c.count());
1214 try testing.expect(c.contains(.a));
1215 try testing.expect(c.contains(.b));
1216 try testing.expect(c.contains(.c));
1217 try testing.expect(c.contains(.d));
1218 try testing.expectEqual(@as(?usize, 1), c.get(.a));
1219 try testing.expectEqual(@as(?usize, 2), c.get(.b));
1220 try testing.expectEqual(@as(?usize, 3), c.get(.c));
1221 try testing.expectEqual(@as(?usize, 4), c.get(.d));
1222
1223 const d = Map.initFullWithDefault(6, .{ .b = 2, .c = 4 });
1224 try testing.expectEqual(@as(usize, 4), d.count());
1225 try testing.expect(d.contains(.a));
1226 try testing.expect(d.contains(.b));
1227 try testing.expect(d.contains(.c));
1228 try testing.expect(d.contains(.d));
1229 try testing.expectEqual(@as(?usize, 6), d.get(.a));
1230 try testing.expectEqual(@as(?usize, 2), d.get(.b));
1231 try testing.expectEqual(@as(?usize, 4), d.get(.c));
1232 try testing.expectEqual(@as(?usize, 6), d.get(.d));
1233
1234 var a = Map.init(.{ .b = 2, .d = 4 });
1235 try testing.expectEqual(@as(usize, 2), a.count());
1236 try testing.expectEqual(false, a.contains(.a));
1237 try testing.expectEqual(true, a.contains(.b));
1238 try testing.expectEqual(false, a.contains(.c));
1239 try testing.expectEqual(true, a.contains(.d));
1240
1241 try testing.expectEqual(@as(?usize, null), a.get(.a));
1242 try testing.expectEqual(@as(?usize, 2), a.get(.b));
1243 try testing.expectEqual(@as(?usize, null), a.get(.c));
1244 try testing.expectEqual(@as(?usize, 4), a.get(.d));
1245
1246 try testing.expectEqual(@as(?*usize, null), a.getPtr(.a));
1247 try testing.expectEqual(@as(?*usize, &a.values[1]), a.getPtr(.b));
1248 try testing.expectEqual(@as(?*usize, null), a.getPtr(.c));
1249 try testing.expectEqual(@as(?*usize, &a.values[3]), a.getPtr(.d));
1250
1251 try testing.expectEqual(@as(?*const usize, null), a.getPtrConst(.a));
1252 try testing.expectEqual(@as(?*const usize, &a.values[1]), a.getPtrConst(.b));
1253 try testing.expectEqual(@as(?*const usize, null), a.getPtrConst(.c));
1254 try testing.expectEqual(@as(?*const usize, &a.values[3]), a.getPtrConst(.d));
1255
1256 try testing.expectEqual(@as(*const usize, &a.values[1]), a.getPtrAssertContains(.b));
1257 try testing.expectEqual(@as(*const usize, &a.values[3]), a.getPtrAssertContains(.d));
1258 try testing.expectEqual(@as(usize, 2), a.getAssertContains(.b));
1259 try testing.expectEqual(@as(usize, 4), a.getAssertContains(.d));
1260
1261 a.put(.a, 3);
1262 a.put(.a, 5);
1263 a.putUninitialized(.c).* = 7;
1264 a.putUninitialized(.c).* = 9;
1265
1266 try testing.expectEqual(@as(usize, 4), a.count());
1267 try testing.expectEqual(@as(?usize, 5), a.get(.a));
1268 try testing.expectEqual(@as(?usize, 2), a.get(.b));
1269 try testing.expectEqual(@as(?usize, 9), a.get(.c));
1270 try testing.expectEqual(@as(?usize, 4), a.get(.d));
1271
1272 a.remove(.a);
1273 try testing.expectEqual(@as(?usize, null), a.fetchRemove(.a));
1274 try testing.expectEqual(@as(?usize, 9), a.fetchRemove(.c));
1275 a.remove(.c);
1276
1277 var iter = a.iterator();
1278 const Entry = Map.Entry;
1279 try testing.expectEqual(@as(?Entry, Entry{
1280 .key = .b,
1281 .value = &a.values[1],
1282 }), iter.next());
1283 try testing.expectEqual(@as(?Entry, Entry{
1284 .key = .d,
1285 .value = &a.values[3],
1286 }), iter.next());
1287 try testing.expectEqual(@as(?Entry, null), iter.next());
1288}
lib/std/event/channel.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const assert = std.debug.assert;8const assert = std.debug.assert;
9const testing = std.testing;9const testing = std.testing;
10const Loop = std.event.Loop;10const Loop = std.event.Loop;
lib/std/event/future.zig+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const assert = std.debug.assert;7const assert = std.debug.assert;
8const testing = std.testing;8const testing = std.testing;
9const builtin = @import("builtin");9const builtin = std.builtin;
10const Lock = std.event.Lock;10const Lock = std.event.Lock;
1111
12/// This is a value that starts out unavailable, until resolve() is called12/// This is a value that starts out unavailable, until resolve() is called
lib/std/event/group.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const Lock = std.event.Lock;8const Lock = std.event.Lock;
9const testing = std.testing;9const testing = std.testing;
10const Allocator = std.mem.Allocator;10const Allocator = std.mem.Allocator;
lib/std/event/lock.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const assert = std.debug.assert;8const assert = std.debug.assert;
9const testing = std.testing;9const testing = std.testing;
10const mem = std.mem;10const mem = std.mem;
lib/std/event/loop.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const root = @import("root");8const root = @import("root");
9const assert = std.debug.assert;9const assert = std.debug.assert;
10const testing = std.testing;10const testing = std.testing;
lib/std/event/rwlock.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const assert = std.debug.assert;8const assert = std.debug.assert;
9const testing = std.testing;9const testing = std.testing;
10const mem = std.mem;10const mem = std.mem;
lib/std/event/wait_group.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const Loop = std.event.Loop;8const Loop = std.event.Loop;
99
10/// A WaitGroup keeps track and waits for a group of async tasks to finish.10/// A WaitGroup keeps track and waits for a group of async tasks to finish.
lib/std/fmt.zig+39-22
...@@ -187,7 +187,7 @@ pub fn format(...@@ -187,7 +187,7 @@ pub fn format(
187187
188 comptime var i = 0;188 comptime var i = 0;
189 inline while (i < fmt.len) {189 inline while (i < fmt.len) {
190 comptime const start_index = i;190 const start_index = i;
191191
192 inline while (i < fmt.len) : (i += 1) {192 inline while (i < fmt.len) : (i += 1) {
193 switch (fmt[i]) {193 switch (fmt[i]) {
...@@ -226,10 +226,10 @@ pub fn format(...@@ -226,10 +226,10 @@ pub fn format(
226 comptime assert(fmt[i] == '{');226 comptime assert(fmt[i] == '{');
227 i += 1;227 i += 1;
228228
229 comptime const fmt_begin = i;229 const fmt_begin = i;
230 // Find the closing brace230 // Find the closing brace
231 inline while (i < fmt.len and fmt[i] != '}') : (i += 1) {}231 inline while (i < fmt.len and fmt[i] != '}') : (i += 1) {}
232 comptime const fmt_end = i;232 const fmt_end = i;
233233
234 if (i >= fmt.len) {234 if (i >= fmt.len) {
235 @compileError("Missing closing }");235 @compileError("Missing closing }");
...@@ -246,23 +246,23 @@ pub fn format(...@@ -246,23 +246,23 @@ pub fn format(
246 parser.pos = 0;246 parser.pos = 0;
247247
248 // Parse the positional argument number248 // Parse the positional argument number
249 comptime const opt_pos_arg = init: {249 const opt_pos_arg = comptime init: {
250 if (comptime parser.maybe('[')) {250 if (parser.maybe('[')) {
251 comptime const arg_name = parser.until(']');251 const arg_name = parser.until(']');
252252
253 if (!comptime parser.maybe(']')) {253 if (!parser.maybe(']')) {
254 @compileError("Expected closing ]");254 @compileError("Expected closing ]");
255 }255 }
256256
257 break :init comptime meta.fieldIndex(ArgsType, arg_name) orelse257 break :init meta.fieldIndex(ArgsType, arg_name) orelse
258 @compileError("No argument with name '" ++ arg_name ++ "'");258 @compileError("No argument with name '" ++ arg_name ++ "'");
259 } else {259 } else {
260 break :init comptime parser.number();260 break :init parser.number();
261 }261 }
262 };262 };
263263
264 // Parse the format specifier264 // Parse the format specifier
265 comptime const specifier_arg = comptime parser.until(':');265 const specifier_arg = comptime parser.until(':');
266266
267 // Skip the colon, if present267 // Skip the colon, if present
268 if (comptime parser.char()) |ch| {268 if (comptime parser.char()) |ch| {
...@@ -302,13 +302,13 @@ pub fn format(...@@ -302,13 +302,13 @@ pub fn format(
302 // Parse the width parameter302 // Parse the width parameter
303 options.width = init: {303 options.width = init: {
304 if (comptime parser.maybe('[')) {304 if (comptime parser.maybe('[')) {
305 comptime const arg_name = parser.until(']');305 const arg_name = comptime parser.until(']');
306306
307 if (!comptime parser.maybe(']')) {307 if (!comptime parser.maybe(']')) {
308 @compileError("Expected closing ]");308 @compileError("Expected closing ]");
309 }309 }
310310
311 comptime const index = meta.fieldIndex(ArgsType, arg_name) orelse311 const index = comptime meta.fieldIndex(ArgsType, arg_name) orelse
312 @compileError("No argument with name '" ++ arg_name ++ "'");312 @compileError("No argument with name '" ++ arg_name ++ "'");
313 const arg_index = comptime arg_state.nextArg(index);313 const arg_index = comptime arg_state.nextArg(index);
314314
...@@ -328,13 +328,13 @@ pub fn format(...@@ -328,13 +328,13 @@ pub fn format(
328 // Parse the precision parameter328 // Parse the precision parameter
329 options.precision = init: {329 options.precision = init: {
330 if (comptime parser.maybe('[')) {330 if (comptime parser.maybe('[')) {
331 comptime const arg_name = parser.until(']');331 const arg_name = comptime parser.until(']');
332332
333 if (!comptime parser.maybe(']')) {333 if (!comptime parser.maybe(']')) {
334 @compileError("Expected closing ]");334 @compileError("Expected closing ]");
335 }335 }
336336
337 comptime const arg_i = meta.fieldIndex(ArgsType, arg_name) orelse337 const arg_i = comptime meta.fieldIndex(ArgsType, arg_name) orelse
338 @compileError("No argument with name '" ++ arg_name ++ "'");338 @compileError("No argument with name '" ++ arg_name ++ "'");
339 const arg_to_use = comptime arg_state.nextArg(arg_i);339 const arg_to_use = comptime arg_state.nextArg(arg_i);
340340
...@@ -905,7 +905,7 @@ pub fn formatBuf(...@@ -905,7 +905,7 @@ pub fn formatBuf(
905) !void {905) !void {
906 if (options.width) |min_width| {906 if (options.width) |min_width| {
907 // In case of error assume the buffer content is ASCII-encoded907 // In case of error assume the buffer content is ASCII-encoded
908 const width = unicode.utf8CountCodepoints(buf) catch |_| buf.len;908 const width = unicode.utf8CountCodepoints(buf) catch buf.len;
909 const padding = if (width < min_width) min_width - width else 0;909 const padding = if (width < min_width) min_width - width else 0;
910910
911 if (padding == 0)911 if (padding == 0)
...@@ -1469,6 +1469,7 @@ pub fn Formatter(comptime format_fn: anytype) type {...@@ -1469,6 +1469,7 @@ pub fn Formatter(comptime format_fn: anytype) type {
1469/// * A prefix of "0x" implies radix=16,1469/// * A prefix of "0x" implies radix=16,
1470/// * Otherwise radix=10 is assumed.1470/// * Otherwise radix=10 is assumed.
1471///1471///
1472/// Ignores '_' character in `buf`.
1472/// See also `parseUnsigned`.1473/// See also `parseUnsigned`.
1473pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) ParseIntError!T {1474pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) ParseIntError!T {
1474 if (buf.len == 0) return error.InvalidCharacter;1475 if (buf.len == 0) return error.InvalidCharacter;
...@@ -1484,6 +1485,10 @@ test "parseInt" {...@@ -1484,6 +1485,10 @@ test "parseInt" {
1484 try std.testing.expectError(error.Overflow, parseInt(u32, "-10", 10));1485 try std.testing.expectError(error.Overflow, parseInt(u32, "-10", 10));
1485 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, " 10", 10));1486 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, " 10", 10));
1486 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "10 ", 10));1487 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "10 ", 10));
1488 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "_10_", 10));
1489 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x_10_", 10));
1490 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x10_", 10));
1491 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x_10", 10));
1487 try std.testing.expect((try parseInt(u8, "255", 10)) == 255);1492 try std.testing.expect((try parseInt(u8, "255", 10)) == 255);
1488 try std.testing.expectError(error.Overflow, parseInt(u8, "256", 10));1493 try std.testing.expectError(error.Overflow, parseInt(u8, "256", 10));
14891494
...@@ -1505,12 +1510,18 @@ test "parseInt" {...@@ -1505,12 +1510,18 @@ test "parseInt" {
15051510
1506 // autodectect the radix1511 // autodectect the radix
1507 try std.testing.expect((try parseInt(i32, "111", 0)) == 111);1512 try std.testing.expect((try parseInt(i32, "111", 0)) == 111);
1513 try std.testing.expect((try parseInt(i32, "1_1_1", 0)) == 111);
1514 try std.testing.expect((try parseInt(i32, "1_1_1", 0)) == 111);
1508 try std.testing.expect((try parseInt(i32, "+0b111", 0)) == 7);1515 try std.testing.expect((try parseInt(i32, "+0b111", 0)) == 7);
1516 try std.testing.expect((try parseInt(i32, "+0b1_11", 0)) == 7);
1509 try std.testing.expect((try parseInt(i32, "+0o111", 0)) == 73);1517 try std.testing.expect((try parseInt(i32, "+0o111", 0)) == 73);
1518 try std.testing.expect((try parseInt(i32, "+0o11_1", 0)) == 73);
1510 try std.testing.expect((try parseInt(i32, "+0x111", 0)) == 273);1519 try std.testing.expect((try parseInt(i32, "+0x111", 0)) == 273);
1511 try std.testing.expect((try parseInt(i32, "-0b111", 0)) == -7);1520 try std.testing.expect((try parseInt(i32, "-0b111", 0)) == -7);
1521 try std.testing.expect((try parseInt(i32, "-0b11_1", 0)) == -7);
1512 try std.testing.expect((try parseInt(i32, "-0o111", 0)) == -73);1522 try std.testing.expect((try parseInt(i32, "-0o111", 0)) == -73);
1513 try std.testing.expect((try parseInt(i32, "-0x111", 0)) == -273);1523 try std.testing.expect((try parseInt(i32, "-0x111", 0)) == -273);
1524 try std.testing.expect((try parseInt(i32, "-0x1_11", 0)) == -273);
15141525
1515 // bare binary/octal/decimal prefix is invalid1526 // bare binary/octal/decimal prefix is invalid
1516 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0b", 0));1527 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0b", 0));
...@@ -1558,7 +1569,10 @@ fn parseWithSign(...@@ -1558,7 +1569,10 @@ fn parseWithSign(
15581569
1559 var x: T = 0;1570 var x: T = 0;
15601571
1572 if (buf_start[0] == '_' or buf_start[buf_start.len - 1] == '_') return error.InvalidCharacter;
1573
1561 for (buf_start) |c| {1574 for (buf_start) |c| {
1575 if (c == '_') continue;
1562 const digit = try charToDigit(c, buf_radix);1576 const digit = try charToDigit(c, buf_radix);
15631577
1564 if (x != 0) x = try math.mul(T, x, try math.cast(T, buf_radix));1578 if (x != 0) x = try math.mul(T, x, try math.cast(T, buf_radix));
...@@ -1577,6 +1591,7 @@ fn parseWithSign(...@@ -1577,6 +1591,7 @@ fn parseWithSign(
1577/// * A prefix of "0x" implies radix=16,1591/// * A prefix of "0x" implies radix=16,
1578/// * Otherwise radix=10 is assumed.1592/// * Otherwise radix=10 is assumed.
1579///1593///
1594/// Ignores '_' character in `buf`.
1580/// See also `parseInt`.1595/// See also `parseInt`.
1581pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseIntError!T {1596pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseIntError!T {
1582 return parseWithSign(T, buf, radix, .Pos);1597 return parseWithSign(T, buf, radix, .Pos);
...@@ -1585,9 +1600,11 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseIntError...@@ -1585,9 +1600,11 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseIntError
1585test "parseUnsigned" {1600test "parseUnsigned" {
1586 try std.testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);1601 try std.testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
1587 try std.testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);1602 try std.testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
1603 try std.testing.expect((try parseUnsigned(u16, "65_535", 10)) == 65535);
1588 try std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));1604 try std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
15891605
1590 try std.testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);1606 try std.testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
1607 try std.testing.expect((try parseUnsigned(u64, "0f_fff_fff_fff_fff_fff", 16)) == 0xffffffffffffffff);
1591 try std.testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));1608 try std.testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
15921609
1593 try std.testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);1610 try std.testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
...@@ -1620,8 +1637,8 @@ pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;...@@ -1620,8 +1637,8 @@ pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
1620pub const parseHexFloat = @import("fmt/parse_hex_float.zig").parseHexFloat;1637pub const parseHexFloat = @import("fmt/parse_hex_float.zig").parseHexFloat;
16211638
1622test {1639test {
1623 _ = @import("fmt/parse_float.zig");1640 _ = parseFloat;
1624 _ = @import("fmt/parse_hex_float.zig");1641 _ = parseHexFloat;
1625}1642}
16261643
1627pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {1644pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
...@@ -2004,7 +2021,7 @@ test "float.special" {...@@ -2004,7 +2021,7 @@ test "float.special" {
2004 try expectFmt("f64: nan", "f64: {}", .{math.nan_f64});2021 try expectFmt("f64: nan", "f64: {}", .{math.nan_f64});
2005 // negative nan is not defined by IEE 754,2022 // negative nan is not defined by IEE 754,
2006 // and ARM thus normalizes it to positive nan2023 // and ARM thus normalizes it to positive nan
2007 if (builtin.arch != builtin.Arch.arm) {2024 if (builtin.target.cpu.arch != .arm) {
2008 try expectFmt("f64: -nan", "f64: {}", .{-math.nan_f64});2025 try expectFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
2009 }2026 }
2010 try expectFmt("f64: inf", "f64: {}", .{math.inf_f64});2027 try expectFmt("f64: inf", "f64: {}", .{math.inf_f64});
...@@ -2015,7 +2032,7 @@ test "float.hexadecimal.special" {...@@ -2015,7 +2032,7 @@ test "float.hexadecimal.special" {
2015 try expectFmt("f64: nan", "f64: {x}", .{math.nan_f64});2032 try expectFmt("f64: nan", "f64: {x}", .{math.nan_f64});
2016 // negative nan is not defined by IEE 754,2033 // negative nan is not defined by IEE 754,
2017 // and ARM thus normalizes it to positive nan2034 // and ARM thus normalizes it to positive nan
2018 if (builtin.arch != builtin.Arch.arm) {2035 if (builtin.target.cpu.arch != .arm) {
2019 try expectFmt("f64: -nan", "f64: {x}", .{-math.nan_f64});2036 try expectFmt("f64: -nan", "f64: {x}", .{-math.nan_f64});
2020 }2037 }
2021 try expectFmt("f64: inf", "f64: {x}", .{math.inf_f64});2038 try expectFmt("f64: inf", "f64: {x}", .{math.inf_f64});
...@@ -2364,15 +2381,15 @@ test "positional/alignment/width/precision" {...@@ -2364,15 +2381,15 @@ test "positional/alignment/width/precision" {
2364}2381}
23652382
2366test "vector" {2383test "vector" {
2367 if (builtin.arch == .mipsel or builtin.arch == .mips) {2384 if (builtin.target.cpu.arch == .mipsel or builtin.target.cpu.arch == .mips) {
2368 // https://github.com/ziglang/zig/issues/33172385 // https://github.com/ziglang/zig/issues/3317
2369 return error.SkipZigTest;2386 return error.SkipZigTest;
2370 }2387 }
2371 if (builtin.arch == .riscv64) {2388 if (builtin.target.cpu.arch == .riscv64) {
2372 // https://github.com/ziglang/zig/issues/44862389 // https://github.com/ziglang/zig/issues/4486
2373 return error.SkipZigTest;2390 return error.SkipZigTest;
2374 }2391 }
2375 if (builtin.arch == .wasm32) {2392 if (builtin.target.cpu.arch == .wasm32) {
2376 // https://github.com/ziglang/zig/issues/53392393 // https://github.com/ziglang/zig/issues/5339
2377 return error.SkipZigTest;2394 return error.SkipZigTest;
2378 }2395 }
lib/std/fs.zig+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");6const builtin = std.builtin;
7const std = @import("std.zig");7const std = @import("std.zig");
8const os = std.os;8const os = std.os;
9const mem = std.mem;9const mem = std.mem;
...@@ -572,7 +572,7 @@ pub const Dir = struct {...@@ -572,7 +572,7 @@ pub const Dir = struct {
572 /// Memory such as file names referenced in this returned entry becomes invalid572 /// Memory such as file names referenced in this returned entry becomes invalid
573 /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized.573 /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized.
574 pub fn next(self: *Self) Error!?Entry {574 pub fn next(self: *Self) Error!?Entry {
575 start_over: while (true) {575 while (true) {
576 const w = os.windows;576 const w = os.windows;
577 if (self.index >= self.end_index) {577 if (self.index >= self.end_index) {
578 var io: w.IO_STATUS_BLOCK = undefined;578 var io: w.IO_STATUS_BLOCK = undefined;
lib/std/fs/file.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const os = std.os;8const os = std.os;
9const io = std.io;9const io = std.io;
10const mem = std.mem;10const mem = std.mem;
lib/std/fs/get_app_data_dir.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const unicode = std.unicode;8const unicode = std.unicode;
9const mem = std.mem;9const mem = std.mem;
10const fs = std.fs;10const fs = std.fs;
lib/std/fs/path.zig+25-24
...@@ -15,22 +15,23 @@ const math = std.math;...@@ -15,22 +15,23 @@ const math = std.math;
15const windows = std.os.windows;15const windows = std.os.windows;
16const fs = std.fs;16const fs = std.fs;
17const process = std.process;17const process = std.process;
18const native_os = builtin.target.os.tag;
1819
19pub const sep_windows = '\\';20pub const sep_windows = '\\';
20pub const sep_posix = '/';21pub const sep_posix = '/';
21pub const sep = if (builtin.os.tag == .windows) sep_windows else sep_posix;22pub const sep = if (native_os == .windows) sep_windows else sep_posix;
2223
23pub const sep_str_windows = "\\";24pub const sep_str_windows = "\\";
24pub const sep_str_posix = "/";25pub const sep_str_posix = "/";
25pub const sep_str = if (builtin.os.tag == .windows) sep_str_windows else sep_str_posix;26pub const sep_str = if (native_os == .windows) sep_str_windows else sep_str_posix;
2627
27pub const delimiter_windows = ';';28pub const delimiter_windows = ';';
28pub const delimiter_posix = ':';29pub const delimiter_posix = ':';
29pub const delimiter = if (builtin.os.tag == .windows) delimiter_windows else delimiter_posix;30pub const delimiter = if (native_os == .windows) delimiter_windows else delimiter_posix;
3031
31/// Returns if the given byte is a valid path separator32/// Returns if the given byte is a valid path separator
32pub fn isSep(byte: u8) bool {33pub fn isSep(byte: u8) bool {
33 if (builtin.os.tag == .windows) {34 if (native_os == .windows) {
34 return byte == '/' or byte == '\\';35 return byte == '/' or byte == '\\';
35 } else {36 } else {
36 return byte == '/';37 return byte == '/';
...@@ -168,7 +169,7 @@ test "join" {...@@ -168,7 +169,7 @@ test "join" {
168pub const isAbsoluteC = @compileError("deprecated: renamed to isAbsoluteZ");169pub const isAbsoluteC = @compileError("deprecated: renamed to isAbsoluteZ");
169170
170pub fn isAbsoluteZ(path_c: [*:0]const u8) bool {171pub fn isAbsoluteZ(path_c: [*:0]const u8) bool {
171 if (builtin.os.tag == .windows) {172 if (native_os == .windows) {
172 return isAbsoluteWindowsZ(path_c);173 return isAbsoluteWindowsZ(path_c);
173 } else {174 } else {
174 return isAbsolutePosixZ(path_c);175 return isAbsolutePosixZ(path_c);
...@@ -176,7 +177,7 @@ pub fn isAbsoluteZ(path_c: [*:0]const u8) bool {...@@ -176,7 +177,7 @@ pub fn isAbsoluteZ(path_c: [*:0]const u8) bool {
176}177}
177178
178pub fn isAbsolute(path: []const u8) bool {179pub fn isAbsolute(path: []const u8) bool {
179 if (builtin.os.tag == .windows) {180 if (native_os == .windows) {
180 return isAbsoluteWindows(path);181 return isAbsoluteWindows(path);
181 } else {182 } else {
182 return isAbsolutePosix(path);183 return isAbsolutePosix(path);
...@@ -365,7 +366,7 @@ test "windowsParsePath" {...@@ -365,7 +366,7 @@ test "windowsParsePath" {
365}366}
366367
367pub fn diskDesignator(path: []const u8) []const u8 {368pub fn diskDesignator(path: []const u8) []const u8 {
368 if (builtin.os.tag == .windows) {369 if (native_os == .windows) {
369 return diskDesignatorWindows(path);370 return diskDesignatorWindows(path);
370 } else {371 } else {
371 return "";372 return "";
...@@ -430,7 +431,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {...@@ -430,7 +431,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {
430431
431/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.432/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.
432pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {433pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
433 if (builtin.os.tag == .windows) {434 if (native_os == .windows) {
434 return resolveWindows(allocator, paths);435 return resolveWindows(allocator, paths);
435 } else {436 } else {
436 return resolvePosix(allocator, paths);437 return resolvePosix(allocator, paths);
...@@ -447,7 +448,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -447,7 +448,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
447/// Without performing actual syscalls, resolving `..` could be incorrect.448/// Without performing actual syscalls, resolving `..` could be incorrect.
448pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {449pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
449 if (paths.len == 0) {450 if (paths.len == 0) {
450 assert(builtin.os.tag == .windows); // resolveWindows called on non windows can't use getCwd451 assert(native_os == .windows); // resolveWindows called on non windows can't use getCwd
451 return process.getCwdAlloc(allocator);452 return process.getCwdAlloc(allocator);
452 }453 }
453454
...@@ -542,7 +543,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -542,7 +543,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
542 result_disk_designator = result[0..result_index];543 result_disk_designator = result[0..result_index];
543 },544 },
544 WindowsPath.Kind.None => {545 WindowsPath.Kind.None => {
545 assert(builtin.os.tag == .windows); // resolveWindows called on non windows can't use getCwd546 assert(native_os == .windows); // resolveWindows called on non windows can't use getCwd
546 const cwd = try process.getCwdAlloc(allocator);547 const cwd = try process.getCwdAlloc(allocator);
547 defer allocator.free(cwd);548 defer allocator.free(cwd);
548 const parsed_cwd = windowsParsePath(cwd);549 const parsed_cwd = windowsParsePath(cwd);
...@@ -557,7 +558,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -557,7 +558,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
557 },558 },
558 }559 }
559 } else {560 } else {
560 assert(builtin.os.tag == .windows); // resolveWindows called on non windows can't use getCwd561 assert(native_os == .windows); // resolveWindows called on non windows can't use getCwd
561 // TODO call get cwd for the result_disk_designator instead of the global one562 // TODO call get cwd for the result_disk_designator instead of the global one
562 const cwd = try process.getCwdAlloc(allocator);563 const cwd = try process.getCwdAlloc(allocator);
563 defer allocator.free(cwd);564 defer allocator.free(cwd);
...@@ -628,7 +629,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -628,7 +629,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
628/// Without performing actual syscalls, resolving `..` could be incorrect.629/// Without performing actual syscalls, resolving `..` could be incorrect.
629pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {630pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
630 if (paths.len == 0) {631 if (paths.len == 0) {
631 assert(builtin.os.tag != .windows); // resolvePosix called on windows can't use getCwd632 assert(native_os != .windows); // resolvePosix called on windows can't use getCwd
632 return process.getCwdAlloc(allocator);633 return process.getCwdAlloc(allocator);
633 }634 }
634635
...@@ -650,7 +651,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -650,7 +651,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
650 if (have_abs) {651 if (have_abs) {
651 result = try allocator.alloc(u8, max_size);652 result = try allocator.alloc(u8, max_size);
652 } else {653 } else {
653 assert(builtin.os.tag != .windows); // resolvePosix called on windows can't use getCwd654 assert(native_os != .windows); // resolvePosix called on windows can't use getCwd
654 const cwd = try process.getCwdAlloc(allocator);655 const cwd = try process.getCwdAlloc(allocator);
655 defer allocator.free(cwd);656 defer allocator.free(cwd);
656 result = try allocator.alloc(u8, max_size + cwd.len + 1);657 result = try allocator.alloc(u8, max_size + cwd.len + 1);
...@@ -690,11 +691,11 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -690,11 +691,11 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
690}691}
691692
692test "resolve" {693test "resolve" {
693 if (builtin.os.tag == .wasi) return error.SkipZigTest;694 if (native_os == .wasi) return error.SkipZigTest;
694695
695 const cwd = try process.getCwdAlloc(testing.allocator);696 const cwd = try process.getCwdAlloc(testing.allocator);
696 defer testing.allocator.free(cwd);697 defer testing.allocator.free(cwd);
697 if (builtin.os.tag == .windows) {698 if (native_os == .windows) {
698 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {699 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
699 cwd[0] = asciiUpper(cwd[0]);700 cwd[0] = asciiUpper(cwd[0]);
700 }701 }
...@@ -706,12 +707,12 @@ test "resolve" {...@@ -706,12 +707,12 @@ test "resolve" {
706}707}
707708
708test "resolveWindows" {709test "resolveWindows" {
709 if (builtin.arch == .aarch64) {710 if (builtin.target.cpu.arch == .aarch64) {
710 // TODO https://github.com/ziglang/zig/issues/3288711 // TODO https://github.com/ziglang/zig/issues/3288
711 return error.SkipZigTest;712 return error.SkipZigTest;
712 }713 }
713 if (builtin.os.tag == .wasi) return error.SkipZigTest;714 if (native_os == .wasi) return error.SkipZigTest;
714 if (builtin.os.tag == .windows) {715 if (native_os == .windows) {
715 const cwd = try process.getCwdAlloc(testing.allocator);716 const cwd = try process.getCwdAlloc(testing.allocator);
716 defer testing.allocator.free(cwd);717 defer testing.allocator.free(cwd);
717 const parsed_cwd = windowsParsePath(cwd);718 const parsed_cwd = windowsParsePath(cwd);
...@@ -755,7 +756,7 @@ test "resolveWindows" {...@@ -755,7 +756,7 @@ test "resolveWindows" {
755}756}
756757
757test "resolvePosix" {758test "resolvePosix" {
758 if (builtin.os.tag == .wasi) return error.SkipZigTest;759 if (native_os == .wasi) return error.SkipZigTest;
759760
760 try testResolvePosix(&[_][]const u8{ "/a/b", "c" }, "/a/b/c");761 try testResolvePosix(&[_][]const u8{ "/a/b", "c" }, "/a/b/c");
761 try testResolvePosix(&[_][]const u8{ "/a/b", "c", "//d", "e///" }, "/d/e");762 try testResolvePosix(&[_][]const u8{ "/a/b", "c", "//d", "e///" }, "/d/e");
...@@ -788,7 +789,7 @@ fn testResolvePosix(paths: []const []const u8, expected: []const u8) !void {...@@ -788,7 +789,7 @@ fn testResolvePosix(paths: []const []const u8, expected: []const u8) !void {
788///789///
789/// If the path is the root directory, returns null.790/// If the path is the root directory, returns null.
790pub fn dirname(path: []const u8) ?[]const u8 {791pub fn dirname(path: []const u8) ?[]const u8 {
791 if (builtin.os.tag == .windows) {792 if (native_os == .windows) {
792 return dirnameWindows(path);793 return dirnameWindows(path);
793 } else {794 } else {
794 return dirnamePosix(path);795 return dirnamePosix(path);
...@@ -922,7 +923,7 @@ fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) !void {...@@ -922,7 +923,7 @@ fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) !void {
922}923}
923924
924pub fn basename(path: []const u8) []const u8 {925pub fn basename(path: []const u8) []const u8 {
925 if (builtin.os.tag == .windows) {926 if (native_os == .windows) {
926 return basenameWindows(path);927 return basenameWindows(path);
927 } else {928 } else {
928 return basenamePosix(path);929 return basenamePosix(path);
...@@ -1038,7 +1039,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) !void {...@@ -1038,7 +1039,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) !void {
1038/// string is returned.1039/// string is returned.
1039/// On Windows this canonicalizes the drive to a capital letter and paths to `\\`.1040/// On Windows this canonicalizes the drive to a capital letter and paths to `\\`.
1040pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 {1041pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 {
1041 if (builtin.os.tag == .windows) {1042 if (native_os == .windows) {
1042 return relativeWindows(allocator, from, to);1043 return relativeWindows(allocator, from, to);
1043 } else {1044 } else {
1044 return relativePosix(allocator, from, to);1045 return relativePosix(allocator, from, to);
...@@ -1164,11 +1165,11 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![...@@ -1164,11 +1165,11 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![
1164}1165}
11651166
1166test "relative" {1167test "relative" {
1167 if (builtin.arch == .aarch64) {1168 if (builtin.target.cpu.arch == .aarch64) {
1168 // TODO https://github.com/ziglang/zig/issues/32881169 // TODO https://github.com/ziglang/zig/issues/3288
1169 return error.SkipZigTest;1170 return error.SkipZigTest;
1170 }1171 }
1171 if (builtin.os.tag == .wasi) return error.SkipZigTest;1172 if (native_os == .wasi) return error.SkipZigTest;
11721173
1173 try testRelativeWindows("c:/blah\\blah", "d:/games", "D:\\games");1174 try testRelativeWindows("c:/blah\\blah", "d:/games", "D:\\games");
1174 try testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa", "..");1175 try testRelativeWindows("c:/aaaa/bbbb", "c:/aaaa", "..");
lib/std/fs/wasi.zig+1-1
...@@ -167,7 +167,7 @@ pub const PreopenList = struct {...@@ -167,7 +167,7 @@ pub const PreopenList = struct {
167};167};
168168
169test "extracting WASI preopens" {169test "extracting WASI preopens" {
170 if (@import("builtin").os.tag != .wasi) return error.SkipZigTest;170 if (std.builtin.os.tag != .wasi) return error.SkipZigTest;
171171
172 var preopens = PreopenList.init(std.testing.allocator);172 var preopens = PreopenList.init(std.testing.allocator);
173 defer preopens.deinit();173 defer preopens.deinit();
lib/std/fs/watch.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const event = std.event;8const event = std.event;
9const assert = std.debug.assert;9const assert = std.debug.assert;
10const testing = std.testing;10const testing = std.testing;
lib/std/hash/auto_hash.zig+3-3
...@@ -4,10 +4,10 @@...@@ -4,10 +4,10 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const builtin = @import("builtin");
8const assert = std.debug.assert;7const assert = std.debug.assert;
9const mem = std.mem;8const mem = std.mem;
10const meta = std.meta;9const meta = std.meta;
10const builtin = std.builtin;
1111
12/// Describes how pointer types should be hashed.12/// Describes how pointer types should be hashed.
13pub const HashStrategy = enum {13pub const HashStrategy = enum {
...@@ -239,7 +239,7 @@ fn testHashDeepRecursive(key: anytype) u64 {...@@ -239,7 +239,7 @@ fn testHashDeepRecursive(key: anytype) u64 {
239239
240test "typeContainsSlice" {240test "typeContainsSlice" {
241 comptime {241 comptime {
242 try testing.expect(!typeContainsSlice(meta.Tag(std.builtin.TypeInfo)));242 try testing.expect(!typeContainsSlice(meta.Tag(builtin.TypeInfo)));
243243
244 try testing.expect(typeContainsSlice([]const u8));244 try testing.expect(typeContainsSlice([]const u8));
245 try testing.expect(!typeContainsSlice(u8));245 try testing.expect(!typeContainsSlice(u8));
...@@ -400,7 +400,7 @@ test "testHash union" {...@@ -400,7 +400,7 @@ test "testHash union" {
400400
401test "testHash vector" {401test "testHash vector" {
402 // Disabled because of #3317402 // Disabled because of #3317
403 if (@import("builtin").arch == .mipsel or @import("builtin").arch == .mips) return error.SkipZigTest;403 if (builtin.target.cpu.arch == .mipsel or builtin.target.cpu.arch == .mips) return error.SkipZigTest;
404404
405 const a: meta.Vector(4, u32) = [_]u32{ 1, 2, 3, 4 };405 const a: meta.Vector(4, u32) = [_]u32{ 1, 2, 3, 4 };
406 const b: meta.Vector(4, u32) = [_]u32{ 1, 2, 3, 5 };406 const b: meta.Vector(4, u32) = [_]u32{ 1, 2, 3, 5 };
lib/std/hash/benchmark.zig+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5// and substantial portions of the software.5// and substantial portions of the software.
6// zig run benchmark.zig --release-fast --override-lib-dir ..6// zig run benchmark.zig --release-fast --override-lib-dir ..
77
8const builtin = @import("builtin");8const builtin = std.builtin;
9const std = @import("std");9const std = @import("std");
10const time = std.time;10const time = std.time;
11const Timer = time.Timer;11const Timer = time.Timer;
lib/std/hash/cityhash.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const builtin = @import("builtin");7const builtin = std.builtin;
88
9fn offsetPtr(ptr: [*]const u8, offset: usize) callconv(.Inline) [*]const u8 {9fn offsetPtr(ptr: [*]const u8, offset: usize) callconv(.Inline) [*]const u8 {
10 // ptr + offset doesn't work at comptime so we need this instead.10 // ptr + offset doesn't work at comptime so we need this instead.
lib/std/hash/crc.zig+2-2
...@@ -28,7 +28,7 @@ pub const Crc32 = Crc32WithPoly(.IEEE);...@@ -28,7 +28,7 @@ pub const Crc32 = Crc32WithPoly(.IEEE);
28pub fn Crc32WithPoly(comptime poly: Polynomial) type {28pub fn Crc32WithPoly(comptime poly: Polynomial) type {
29 return struct {29 return struct {
30 const Self = @This();30 const Self = @This();
31 const lookup_tables = comptime block: {31 const lookup_tables = block: {
32 @setEvalBranchQuota(20000);32 @setEvalBranchQuota(20000);
33 var tables: [8][256]u32 = undefined;33 var tables: [8][256]u32 = undefined;
3434
...@@ -128,7 +128,7 @@ test "crc32 castagnoli" {...@@ -128,7 +128,7 @@ test "crc32 castagnoli" {
128pub fn Crc32SmallWithPoly(comptime poly: Polynomial) type {128pub fn Crc32SmallWithPoly(comptime poly: Polynomial) type {
129 return struct {129 return struct {
130 const Self = @This();130 const Self = @This();
131 const lookup_table = comptime block: {131 const lookup_table = block: {
132 var table: [16]u32 = undefined;132 var table: [16]u32 = undefined;
133133
134 for (table) |*e, i| {134 for (table) |*e, i| {
lib/std/hash/murmur.zig+9-8
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6const std = @import("std");6const std = @import("std");
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const testing = std.testing;8const testing = std.testing;
9const native_endian = builtin.target.cpu.arch.endian();
910
10const default_seed: u32 = 0xc70f6907;11const default_seed: u32 = 0xc70f6907;
1112
...@@ -22,7 +23,7 @@ pub const Murmur2_32 = struct {...@@ -22,7 +23,7 @@ pub const Murmur2_32 = struct {
22 var h1: u32 = seed ^ len;23 var h1: u32 = seed ^ len;
23 for (@ptrCast([*]align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {24 for (@ptrCast([*]align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {
24 var k1: u32 = v;25 var k1: u32 = v;
25 if (builtin.endian == .Big)26 if (native_endian == .Big)
26 k1 = @byteSwap(u32, k1);27 k1 = @byteSwap(u32, k1);
27 k1 *%= m;28 k1 *%= m;
28 k1 ^= k1 >> 24;29 k1 ^= k1 >> 24;
...@@ -107,7 +108,7 @@ pub const Murmur2_64 = struct {...@@ -107,7 +108,7 @@ pub const Murmur2_64 = struct {
107 var h1: u64 = seed ^ (len *% m);108 var h1: u64 = seed ^ (len *% m);
108 for (@ptrCast([*]align(1) const u64, str.ptr)[0..@intCast(usize, len >> 3)]) |v| {109 for (@ptrCast([*]align(1) const u64, str.ptr)[0..@intCast(usize, len >> 3)]) |v| {
109 var k1: u64 = v;110 var k1: u64 = v;
110 if (builtin.endian == .Big)111 if (native_endian == .Big)
111 k1 = @byteSwap(u64, k1);112 k1 = @byteSwap(u64, k1);
112 k1 *%= m;113 k1 *%= m;
113 k1 ^= k1 >> 47;114 k1 ^= k1 >> 47;
...@@ -120,7 +121,7 @@ pub const Murmur2_64 = struct {...@@ -120,7 +121,7 @@ pub const Murmur2_64 = struct {
120 if (rest > 0) {121 if (rest > 0) {
121 var k1: u64 = 0;122 var k1: u64 = 0;
122 @memcpy(@ptrCast([*]u8, &k1), @ptrCast([*]const u8, &str[@intCast(usize, offset)]), @intCast(usize, rest));123 @memcpy(@ptrCast([*]u8, &k1), @ptrCast([*]const u8, &str[@intCast(usize, offset)]), @intCast(usize, rest));
123 if (builtin.endian == .Big)124 if (native_endian == .Big)
124 k1 = @byteSwap(u64, k1);125 k1 = @byteSwap(u64, k1);
125 h1 ^= k1;126 h1 ^= k1;
126 h1 *%= m;127 h1 *%= m;
...@@ -187,7 +188,7 @@ pub const Murmur3_32 = struct {...@@ -187,7 +188,7 @@ pub const Murmur3_32 = struct {
187 var h1: u32 = seed;188 var h1: u32 = seed;
188 for (@ptrCast([*]align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {189 for (@ptrCast([*]align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {
189 var k1: u32 = v;190 var k1: u32 = v;
190 if (builtin.endian == .Big)191 if (native_endian == .Big)
191 k1 = @byteSwap(u32, k1);192 k1 = @byteSwap(u32, k1);
192 k1 *%= c1;193 k1 *%= c1;
193 k1 = rotl32(k1, 15);194 k1 = rotl32(k1, 15);
...@@ -299,7 +300,7 @@ fn SMHasherTest(comptime hash_fn: anytype, comptime hashbits: u32) u32 {...@@ -299,7 +300,7 @@ fn SMHasherTest(comptime hash_fn: anytype, comptime hashbits: u32) u32 {
299 key[i] = @truncate(u8, i);300 key[i] = @truncate(u8, i);
300301
301 var h = hash_fn(key[0..i], 256 - i);302 var h = hash_fn(key[0..i], 256 - i);
302 if (builtin.endian == .Big)303 if (native_endian == .Big)
303 h = @byteSwap(@TypeOf(h), h);304 h = @byteSwap(@TypeOf(h), h);
304 @memcpy(@ptrCast([*]u8, &hashes[i * hashbytes]), @ptrCast([*]u8, &h), hashbytes);305 @memcpy(@ptrCast([*]u8, &hashes[i * hashbytes]), @ptrCast([*]u8, &h), hashbytes);
305 }306 }
...@@ -313,7 +314,7 @@ test "murmur2_32" {...@@ -313,7 +314,7 @@ test "murmur2_32" {
313 var v1: u64 = 0x1234567812345678;314 var v1: u64 = 0x1234567812345678;
314 var v0le: u32 = v0;315 var v0le: u32 = v0;
315 var v1le: u64 = v1;316 var v1le: u64 = v1;
316 if (builtin.endian == .Big) {317 if (native_endian == .Big) {
317 v0le = @byteSwap(u32, v0le);318 v0le = @byteSwap(u32, v0le);
318 v1le = @byteSwap(u64, v1le);319 v1le = @byteSwap(u64, v1le);
319 }320 }
...@@ -327,7 +328,7 @@ test "murmur2_64" {...@@ -327,7 +328,7 @@ test "murmur2_64" {
327 var v1: u64 = 0x1234567812345678;328 var v1: u64 = 0x1234567812345678;
328 var v0le: u32 = v0;329 var v0le: u32 = v0;
329 var v1le: u64 = v1;330 var v1le: u64 = v1;
330 if (builtin.endian == .Big) {331 if (native_endian == .Big) {
331 v0le = @byteSwap(u32, v0le);332 v0le = @byteSwap(u32, v0le);
332 v1le = @byteSwap(u64, v1le);333 v1le = @byteSwap(u64, v1le);
333 }334 }
...@@ -341,7 +342,7 @@ test "murmur3_32" {...@@ -341,7 +342,7 @@ test "murmur3_32" {
341 var v1: u64 = 0x1234567812345678;342 var v1: u64 = 0x1234567812345678;
342 var v0le: u32 = v0;343 var v0le: u32 = v0;
343 var v1le: u64 = v1;344 var v1le: u64 = v1;
344 if (builtin.endian == .Big) {345 if (native_endian == .Big) {
345 v0le = @byteSwap(u32, v0le);346 v0le = @byteSwap(u32, v0le);
346 v1le = @byteSwap(u64, v1le);347 v1le = @byteSwap(u64, v1le);
347 }348 }
lib/std/hash_map.zig-1
...@@ -4,7 +4,6 @@...@@ -4,7 +4,6 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std.zig");6const std = @import("std.zig");
7const builtin = @import("builtin");
8const assert = debug.assert;7const assert = debug.assert;
9const autoHash = std.hash.autoHash;8const autoHash = std.hash.autoHash;
10const debug = std.debug;9const debug = std.debug;
lib/std/heap.zig+4-4
...@@ -10,7 +10,7 @@ const assert = debug.assert;...@@ -10,7 +10,7 @@ const assert = debug.assert;
10const testing = std.testing;10const testing = std.testing;
11const mem = std.mem;11const mem = std.mem;
12const os = std.os;12const os = std.os;
13const builtin = @import("builtin");13const builtin = std.builtin;
14const c = std.c;14const c = std.c;
15const maxInt = std.math.maxInt;15const maxInt = std.math.maxInt;
1616
...@@ -28,17 +28,17 @@ const CAllocator = struct {...@@ -28,17 +28,17 @@ const CAllocator = struct {
28 }28 }
29 }29 }
3030
31 usingnamespace if (comptime @hasDecl(c, "malloc_size"))31 usingnamespace if (@hasDecl(c, "malloc_size"))
32 struct {32 struct {
33 pub const supports_malloc_size = true;33 pub const supports_malloc_size = true;
34 pub const malloc_size = c.malloc_size;34 pub const malloc_size = c.malloc_size;
35 }35 }
36 else if (comptime @hasDecl(c, "malloc_usable_size"))36 else if (@hasDecl(c, "malloc_usable_size"))
37 struct {37 struct {
38 pub const supports_malloc_size = true;38 pub const supports_malloc_size = true;
39 pub const malloc_size = c.malloc_usable_size;39 pub const malloc_size = c.malloc_usable_size;
40 }40 }
41 else if (comptime @hasDecl(c, "_msize"))41 else if (@hasDecl(c, "_msize"))
42 struct {42 struct {
43 pub const supports_malloc_size = true;43 pub const supports_malloc_size = true;
44 pub const malloc_size = c._msize;44 pub const malloc_size = c._msize;
lib/std/heap/general_purpose_allocator.zig+7-2
...@@ -317,7 +317,10 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -317,7 +317,10 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
317 if (is_used) {317 if (is_used) {
318 const slot_index = @intCast(SlotIndex, used_bits_byte * 8 + bit_index);318 const slot_index = @intCast(SlotIndex, used_bits_byte * 8 + bit_index);
319 const stack_trace = bucketStackTrace(bucket, size_class, slot_index, .alloc);319 const stack_trace = bucketStackTrace(bucket, size_class, slot_index, .alloc);
320 log.err("Memory leak detected: {s}", .{stack_trace});320 const addr = bucket.page + slot_index * size_class;
321 log.err("memory address 0x{x} leaked: {s}", .{
322 @ptrToInt(addr), stack_trace,
323 });
321 leaks = true;324 leaks = true;
322 }325 }
323 if (bit_index == math.maxInt(u3))326 if (bit_index == math.maxInt(u3))
...@@ -345,7 +348,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -345,7 +348,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
345 }348 }
346 var it = self.large_allocations.iterator();349 var it = self.large_allocations.iterator();
347 while (it.next()) |large_alloc| {350 while (it.next()) |large_alloc| {
348 log.err("Memory leak detected: {s}", .{large_alloc.value.getStackTrace()});351 log.err("memory address 0x{x} leaked: {s}", .{
352 @ptrToInt(large_alloc.value.bytes.ptr), large_alloc.value.getStackTrace(),
353 });
349 leaks = true;354 leaks = true;
350 }355 }
351 return leaks;356 return leaks;
lib/std/io.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std.zig");6const std = @import("std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const root = @import("root");8const root = @import("root");
9const c = std.c;9const c = std.c;
1010
lib/std/io/bit_reader.zig+3-3
...@@ -23,9 +23,9 @@ pub fn BitReader(endian: builtin.Endian, comptime ReaderType: type) type {...@@ -23,9 +23,9 @@ pub fn BitReader(endian: builtin.Endian, comptime ReaderType: type) type {
23 pub const Reader = io.Reader(*Self, Error, read);23 pub const Reader = io.Reader(*Self, Error, read);
2424
25 const Self = @This();25 const Self = @This();
26 const u8_bit_count = comptime meta.bitCount(u8);26 const u8_bit_count = meta.bitCount(u8);
27 const u7_bit_count = comptime meta.bitCount(u7);27 const u7_bit_count = meta.bitCount(u7);
28 const u4_bit_count = comptime meta.bitCount(u4);28 const u4_bit_count = meta.bitCount(u4);
2929
30 pub fn init(forward_reader: ReaderType) Self {30 pub fn init(forward_reader: ReaderType) Self {
31 return Self{31 return Self{
lib/std/io/bit_writer.zig+2-2
...@@ -23,8 +23,8 @@ pub fn BitWriter(endian: builtin.Endian, comptime WriterType: type) type {...@@ -23,8 +23,8 @@ pub fn BitWriter(endian: builtin.Endian, comptime WriterType: type) type {
23 pub const Writer = io.Writer(*Self, Error, write);23 pub const Writer = io.Writer(*Self, Error, write);
2424
25 const Self = @This();25 const Self = @This();
26 const u8_bit_count = comptime meta.bitCount(u8);26 const u8_bit_count = meta.bitCount(u8);
27 const u4_bit_count = comptime meta.bitCount(u4);27 const u4_bit_count = meta.bitCount(u4);
2828
29 pub fn init(forward_writer: WriterType) Self {29 pub fn init(forward_writer: WriterType) Self {
30 return Self{30 return Self{
lib/std/io/test.zig+4-3
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const builtin = std.builtin;7const builtin = @import("builtin");
8const io = std.io;8const io = std.io;
9const meta = std.meta;9const meta = std.meta;
10const trait = std.trait;10const trait = std.trait;
...@@ -15,6 +15,7 @@ const expectError = std.testing.expectError;...@@ -15,6 +15,7 @@ const expectError = std.testing.expectError;
15const mem = std.mem;15const mem = std.mem;
16const fs = std.fs;16const fs = std.fs;
17const File = std.fs.File;17const File = std.fs.File;
18const native_endian = builtin.target.cpu.arch.endian();
1819
19const tmpDir = std.testing.tmpDir;20const tmpDir = std.testing.tmpDir;
2021
...@@ -72,7 +73,7 @@ test "BitStreams with File Stream" {...@@ -72,7 +73,7 @@ test "BitStreams with File Stream" {
72 var file = try tmp.dir.createFile(tmp_file_name, .{});73 var file = try tmp.dir.createFile(tmp_file_name, .{});
73 defer file.close();74 defer file.close();
7475
75 var bit_stream = io.bitWriter(builtin.endian, file.writer());76 var bit_stream = io.bitWriter(native_endian, file.writer());
7677
77 try bit_stream.writeBits(@as(u2, 1), 1);78 try bit_stream.writeBits(@as(u2, 1), 1);
78 try bit_stream.writeBits(@as(u5, 2), 2);79 try bit_stream.writeBits(@as(u5, 2), 2);
...@@ -86,7 +87,7 @@ test "BitStreams with File Stream" {...@@ -86,7 +87,7 @@ test "BitStreams with File Stream" {
86 var file = try tmp.dir.openFile(tmp_file_name, .{});87 var file = try tmp.dir.openFile(tmp_file_name, .{});
87 defer file.close();88 defer file.close();
8889
89 var bit_stream = io.bitReader(builtin.endian, file.reader());90 var bit_stream = io.bitReader(native_endian, file.reader());
9091
91 var out_bits: usize = undefined;92 var out_bits: usize = undefined;
9293
lib/std/json.zig+2-2
...@@ -195,7 +195,7 @@ pub const StreamingParser = struct {...@@ -195,7 +195,7 @@ pub const StreamingParser = struct {
195 p.number_is_integer = undefined;195 p.number_is_integer = undefined;
196 }196 }
197197
198 pub const State = enum {198 pub const State = enum(u8) {
199 // These must be first with these explicit values as we rely on them for indexing the199 // These must be first with these explicit values as we rely on them for indexing the
200 // bit-stack directly and avoiding a branch.200 // bit-stack directly and avoiding a branch.
201 ObjectSeparator = 0,201 ObjectSeparator = 0,
...@@ -1781,7 +1781,7 @@ test "parse" {...@@ -1781,7 +1781,7 @@ test "parse" {
1781}1781}
17821782
1783test "parse into enum" {1783test "parse into enum" {
1784 const T = extern enum {1784 const T = enum(u32) {
1785 Foo = 42,1785 Foo = 42,
1786 Bar,1786 Bar,
1787 @"with\\escape",1787 @"with\\escape",
lib/std/macho.zig+3-3
...@@ -1365,7 +1365,7 @@ pub const BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: u8 = 0xa0;...@@ -1365,7 +1365,7 @@ pub const BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: u8 = 0xa0;
1365pub const BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: u8 = 0xb0;1365pub const BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: u8 = 0xb0;
1366pub const BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: u8 = 0xc0;1366pub const BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: u8 = 0xc0;
13671367
1368pub const reloc_type_x86_64 = packed enum(u4) {1368pub const reloc_type_x86_64 = enum(u4) {
1369 /// for absolute addresses1369 /// for absolute addresses
1370 X86_64_RELOC_UNSIGNED = 0,1370 X86_64_RELOC_UNSIGNED = 0,
13711371
...@@ -1397,9 +1397,9 @@ pub const reloc_type_x86_64 = packed enum(u4) {...@@ -1397,9 +1397,9 @@ pub const reloc_type_x86_64 = packed enum(u4) {
1397 X86_64_RELOC_TLV,1397 X86_64_RELOC_TLV,
1398};1398};
13991399
1400pub const reloc_type_arm64 = packed enum(u4) {1400pub const reloc_type_arm64 = enum(u4) {
1401 /// For pointers.1401 /// For pointers.
1402 ARM64_RELOC_UNSIGNED = 0,1402 ARM64_RELOC_UNSIGNED,
14031403
1404 /// Must be followed by a ARM64_RELOC_UNSIGNED.1404 /// Must be followed by a ARM64_RELOC_UNSIGNED.
1405 ARM64_RELOC_SUBTRACTOR,1405 ARM64_RELOC_SUBTRACTOR,
lib/std/math.zig+6-6
...@@ -986,9 +986,9 @@ pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) std.meta.Int(@typeInfo(...@@ -986,9 +986,9 @@ pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) std.meta.Int(@typeInfo(
986 comptime assert(@typeInfo(T) == .Int);986 comptime assert(@typeInfo(T) == .Int);
987 comptime assert(@typeInfo(T).Int.signedness == .unsigned);987 comptime assert(@typeInfo(T).Int.signedness == .unsigned);
988 assert(value != 0);988 assert(value != 0);
989 comptime const PromotedType = std.meta.Int(@typeInfo(T).Int.signedness, @typeInfo(T).Int.bits + 1);989 const PromotedType = std.meta.Int(@typeInfo(T).Int.signedness, @typeInfo(T).Int.bits + 1);
990 comptime const shiftType = std.math.Log2Int(PromotedType);990 const ShiftType = std.math.Log2Int(PromotedType);
991 return @as(PromotedType, 1) << @intCast(shiftType, @typeInfo(T).Int.bits - @clz(T, value - 1));991 return @as(PromotedType, 1) << @intCast(ShiftType, @typeInfo(T).Int.bits - @clz(T, value - 1));
992}992}
993993
994/// Returns the next power of two (if the value is not already a power of two).994/// Returns the next power of two (if the value is not already a power of two).
...@@ -998,8 +998,8 @@ pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) {...@@ -998,8 +998,8 @@ pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) {
998 comptime assert(@typeInfo(T) == .Int);998 comptime assert(@typeInfo(T) == .Int);
999 const info = @typeInfo(T).Int;999 const info = @typeInfo(T).Int;
1000 comptime assert(info.signedness == .unsigned);1000 comptime assert(info.signedness == .unsigned);
1001 comptime const PromotedType = std.meta.Int(info.signedness, info.bits + 1);1001 const PromotedType = std.meta.Int(info.signedness, info.bits + 1);
1002 comptime const overflowBit = @as(PromotedType, 1) << info.bits;1002 const overflowBit = @as(PromotedType, 1) << info.bits;
1003 var x = ceilPowerOfTwoPromote(T, value);1003 var x = ceilPowerOfTwoPromote(T, value);
1004 if (overflowBit & x != 0) {1004 if (overflowBit & x != 0) {
1005 return error.Overflow;1005 return error.Overflow;
...@@ -1327,7 +1327,7 @@ test "order.compare" {...@@ -1327,7 +1327,7 @@ test "order.compare" {
1327}1327}
13281328
1329test "math.comptime" {1329test "math.comptime" {
1330 comptime const v = sin(@as(f32, 1)) + ln(@as(f32, 5));1330 const v = comptime (sin(@as(f32, 1)) + ln(@as(f32, 5)));
1331 try testing.expect(v == sin(@as(f32, 1)) + ln(@as(f32, 5)));1331 try testing.expect(v == sin(@as(f32, 1)) + ln(@as(f32, 5)));
1332}1332}
13331333
lib/std/math/acosh.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/math/acoshf.c9// https://git.musl-libc.org/cgit/musl/tree/src/math/acoshf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/math/acosh.c10// https://git.musl-libc.org/cgit/musl/tree/src/math/acosh.c
1111
12const builtin = @import("builtin");
13const std = @import("../std.zig");12const std = @import("../std.zig");
14const math = std.math;13const math = std.math;
15const expect = std.testing.expect;14const expect = std.testing.expect;
lib/std/math/ceil.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c9// https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c10// https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c
1111
12const builtin = @import("builtin");
13const std = @import("../std.zig");12const std = @import("../std.zig");
14const math = std.math;13const math = std.math;
15const expect = std.testing.expect;14const expect = std.testing.expect;
lib/std/math/complex/atan.zig-1
...@@ -10,7 +10,6 @@...@@ -10,7 +10,6 @@
10// https://git.musl-libc.org/cgit/musl/tree/src/complex/catan.c10// https://git.musl-libc.org/cgit/musl/tree/src/complex/catan.c
1111
12const std = @import("../../std.zig");12const std = @import("../../std.zig");
13const builtin = @import("builtin");
14const testing = std.testing;13const testing = std.testing;
15const math = std.math;14const math = std.math;
16const cmath = math.complex;15const cmath = math.complex;
lib/std/math/complex/cosh.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/complex/ccoshf.c9// https://git.musl-libc.org/cgit/musl/tree/src/complex/ccoshf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/complex/ccosh.c10// https://git.musl-libc.org/cgit/musl/tree/src/complex/ccosh.c
1111
12const builtin = @import("builtin");
13const std = @import("../../std.zig");12const std = @import("../../std.zig");
14const testing = std.testing;13const testing = std.testing;
15const math = std.math;14const math = std.math;
lib/std/math/complex/exp.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/complex/cexpf.c9// https://git.musl-libc.org/cgit/musl/tree/src/complex/cexpf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/complex/cexp.c10// https://git.musl-libc.org/cgit/musl/tree/src/complex/cexp.c
1111
12const builtin = @import("builtin");
13const std = @import("../../std.zig");12const std = @import("../../std.zig");
14const testing = std.testing;13const testing = std.testing;
15const math = std.math;14const math = std.math;
lib/std/math/complex/sinh.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/complex/csinhf.c9// https://git.musl-libc.org/cgit/musl/tree/src/complex/csinhf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/complex/csinh.c10// https://git.musl-libc.org/cgit/musl/tree/src/complex/csinh.c
1111
12const builtin = @import("builtin");
13const std = @import("../../std.zig");12const std = @import("../../std.zig");
14const testing = std.testing;13const testing = std.testing;
15const math = std.math;14const math = std.math;
lib/std/math/complex/tanh.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/complex/ctanhf.c9// https://git.musl-libc.org/cgit/musl/tree/src/complex/ctanhf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/complex/ctanh.c10// https://git.musl-libc.org/cgit/musl/tree/src/complex/ctanh.c
1111
12const builtin = @import("builtin");
13const std = @import("../../std.zig");12const std = @import("../../std.zig");
14const testing = std.testing;13const testing = std.testing;
15const math = std.math;14const math = std.math;
lib/std/math/cos.zig-1
...@@ -8,7 +8,6 @@...@@ -8,7 +8,6 @@
8//8//
9// https://golang.org/src/math/sin.go9// https://golang.org/src/math/sin.go
1010
11const builtin = @import("builtin");
12const std = @import("../std.zig");11const std = @import("../std.zig");
13const math = std.math;12const math = std.math;
14const expect = std.testing.expect;13const expect = std.testing.expect;
lib/std/math/cosh.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/math/coshf.c9// https://git.musl-libc.org/cgit/musl/tree/src/math/coshf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/math/cosh.c10// https://git.musl-libc.org/cgit/musl/tree/src/math/cosh.c
1111
12const builtin = @import("builtin");
13const std = @import("../std.zig");12const std = @import("../std.zig");
14const math = std.math;13const math = std.math;
15const expo2 = @import("expo2.zig").expo2;14const expo2 = @import("expo2.zig").expo2;
lib/std/math/expm1.zig-1
...@@ -11,7 +11,6 @@...@@ -11,7 +11,6 @@
1111
12// TODO: Updated recently.12// TODO: Updated recently.
1313
14const builtin = @import("builtin");
15const std = @import("../std.zig");14const std = @import("../std.zig");
16const math = std.math;15const math = std.math;
17const expect = std.testing.expect;16const expect = std.testing.expect;
lib/std/math/floor.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/math/floorf.c9// https://git.musl-libc.org/cgit/musl/tree/src/math/floorf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/math/floor.c10// https://git.musl-libc.org/cgit/musl/tree/src/math/floor.c
1111
12const builtin = @import("builtin");
13const expect = std.testing.expect;12const expect = std.testing.expect;
14const std = @import("../std.zig");13const std = @import("../std.zig");
15const math = std.math;14const math = std.math;
lib/std/math/log1p.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/math/log1pf.c9// https://git.musl-libc.org/cgit/musl/tree/src/math/log1pf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/math/log1p.c10// https://git.musl-libc.org/cgit/musl/tree/src/math/log1p.c
1111
12const builtin = @import("builtin");
13const std = @import("../std.zig");12const std = @import("../std.zig");
14const math = std.math;13const math = std.math;
15const expect = std.testing.expect;14const expect = std.testing.expect;
lib/std/math/pow.zig-1
...@@ -8,7 +8,6 @@...@@ -8,7 +8,6 @@
8//8//
9// https://golang.org/src/math/pow.go9// https://golang.org/src/math/pow.go
1010
11const builtin = @import("builtin");
12const std = @import("../std.zig");11const std = @import("../std.zig");
13const math = std.math;12const math = std.math;
14const expect = std.testing.expect;13const expect = std.testing.expect;
lib/std/math/powi.zig-1
...@@ -8,7 +8,6 @@...@@ -8,7 +8,6 @@
8//8//
9// https://github.com/rust-lang/rust/blob/360432f1e8794de58cd94f34c9c17ad65871e5b5/src/libcore/num/mod.rs#L34239// https://github.com/rust-lang/rust/blob/360432f1e8794de58cd94f34c9c17ad65871e5b5/src/libcore/num/mod.rs#L3423
1010
11const builtin = @import("builtin");
12const std = @import("../std.zig");11const std = @import("../std.zig");
13const math = std.math;12const math = std.math;
14const assert = std.debug.assert;13const assert = std.debug.assert;
lib/std/math/round.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/math/roundf.c9// https://git.musl-libc.org/cgit/musl/tree/src/math/roundf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/math/round.c10// https://git.musl-libc.org/cgit/musl/tree/src/math/round.c
1111
12const builtin = @import("builtin");
13const expect = std.testing.expect;12const expect = std.testing.expect;
14const std = @import("../std.zig");13const std = @import("../std.zig");
15const math = std.math;14const math = std.math;
lib/std/math/sin.zig-1
...@@ -8,7 +8,6 @@...@@ -8,7 +8,6 @@
8//8//
9// https://golang.org/src/math/sin.go9// https://golang.org/src/math/sin.go
1010
11const builtin = @import("builtin");
12const std = @import("../std.zig");11const std = @import("../std.zig");
13const math = std.math;12const math = std.math;
14const expect = std.testing.expect;13const expect = std.testing.expect;
lib/std/math/sinh.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/math/sinhf.c9// https://git.musl-libc.org/cgit/musl/tree/src/math/sinhf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/math/sinh.c10// https://git.musl-libc.org/cgit/musl/tree/src/math/sinh.c
1111
12const builtin = @import("builtin");
13const std = @import("../std.zig");12const std = @import("../std.zig");
14const math = std.math;13const math = std.math;
15const expect = std.testing.expect;14const expect = std.testing.expect;
lib/std/math/sqrt.zig+1-2
...@@ -6,8 +6,7 @@...@@ -6,8 +6,7 @@
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const math = std.math;7const math = std.math;
8const expect = std.testing.expect;8const expect = std.testing.expect;
9const builtin = @import("builtin");9const TypeId = std.builtin.TypeId;
10const TypeId = builtin.TypeId;
11const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
1211
13/// Returns the square root of x.12/// Returns the square root of x.
lib/std/math/tan.zig-1
...@@ -8,7 +8,6 @@...@@ -8,7 +8,6 @@
8//8//
9// https://golang.org/src/math/tan.go9// https://golang.org/src/math/tan.go
1010
11const builtin = @import("builtin");
12const std = @import("../std.zig");11const std = @import("../std.zig");
13const math = std.math;12const math = std.math;
14const expect = std.testing.expect;13const expect = std.testing.expect;
lib/std/math/tanh.zig-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9// https://git.musl-libc.org/cgit/musl/tree/src/math/tanhf.c9// https://git.musl-libc.org/cgit/musl/tree/src/math/tanhf.c
10// https://git.musl-libc.org/cgit/musl/tree/src/math/tanh.c10// https://git.musl-libc.org/cgit/musl/tree/src/math/tanh.c
1111
12const builtin = @import("builtin");
13const std = @import("../std.zig");12const std = @import("../std.zig");
14const math = std.math;13const math = std.math;
15const expect = std.testing.expect;14const expect = std.testing.expect;
lib/std/mem.zig+47-46
...@@ -7,17 +7,18 @@ const std = @import("std.zig");...@@ -7,17 +7,18 @@ const std = @import("std.zig");
7const debug = std.debug;7const debug = std.debug;
8const assert = debug.assert;8const assert = debug.assert;
9const math = std.math;9const math = std.math;
10const builtin = std.builtin;
11const mem = @This();10const mem = @This();
12const meta = std.meta;11const meta = std.meta;
13const trait = meta.trait;12const trait = meta.trait;
14const testing = std.testing;13const testing = std.testing;
14const Endian = std.builtin.Endian;
15const native_endian = std.Target.current.cpu.arch.endian();
1516
16/// Compile time known minimum page size.17/// Compile time known minimum page size.
17/// https://github.com/ziglang/zig/issues/408218/// https://github.com/ziglang/zig/issues/4082
18pub const page_size = switch (builtin.arch) {19pub const page_size = switch (std.Target.current.cpu.arch) {
19 .wasm32, .wasm64 => 64 * 1024,20 .wasm32, .wasm64 => 64 * 1024,
20 .aarch64 => switch (builtin.os.tag) {21 .aarch64 => switch (std.Target.current.os.tag) {
21 .macos, .ios, .watchos, .tvos => 16 * 1024,22 .macos, .ios, .watchos, .tvos => 16 * 1024,
22 else => 4 * 1024,23 else => 4 * 1024,
23 },24 },
...@@ -355,7 +356,7 @@ test "mem.zeroes" {...@@ -355,7 +356,7 @@ test "mem.zeroes" {
355/// If the field is present in the provided initial values, it will have that value instead.356/// If the field is present in the provided initial values, it will have that value instead.
356/// Structs are initialized recursively.357/// Structs are initialized recursively.
357pub fn zeroInit(comptime T: type, init: anytype) T {358pub fn zeroInit(comptime T: type, init: anytype) T {
358 comptime const Init = @TypeOf(init);359 const Init = @TypeOf(init);
359360
360 switch (@typeInfo(T)) {361 switch (@typeInfo(T)) {
361 .Struct => |struct_info| {362 .Struct => |struct_info| {
...@@ -1230,7 +1231,7 @@ test "mem.containsAtLeast" {...@@ -1230,7 +1231,7 @@ test "mem.containsAtLeast" {
1230/// Reads an integer from memory with size equal to bytes.len.1231/// Reads an integer from memory with size equal to bytes.len.
1231/// T specifies the return type, which must be large enough to store1232/// T specifies the return type, which must be large enough to store
1232/// the result.1233/// the result.
1233pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.Endian) ReturnType {1234pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: Endian) ReturnType {
1234 var result: ReturnType = 0;1235 var result: ReturnType = 0;
1235 switch (endian) {1236 switch (endian) {
1236 .Big => {1237 .Big => {
...@@ -1265,12 +1266,12 @@ pub fn readIntForeign(comptime T: type, bytes: *const [@divExact(@typeInfo(T).In...@@ -1265,12 +1266,12 @@ pub fn readIntForeign(comptime T: type, bytes: *const [@divExact(@typeInfo(T).In
1265 return @byteSwap(T, readIntNative(T, bytes));1266 return @byteSwap(T, readIntNative(T, bytes));
1266}1267}
12671268
1268pub const readIntLittle = switch (builtin.endian) {1269pub const readIntLittle = switch (native_endian) {
1269 .Little => readIntNative,1270 .Little => readIntNative,
1270 .Big => readIntForeign,1271 .Big => readIntForeign,
1271};1272};
12721273
1273pub const readIntBig = switch (builtin.endian) {1274pub const readIntBig = switch (native_endian) {
1274 .Little => readIntForeign,1275 .Little => readIntForeign,
1275 .Big => readIntNative,1276 .Big => readIntNative,
1276};1277};
...@@ -1294,12 +1295,12 @@ pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {...@@ -1294,12 +1295,12 @@ pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {
1294 return @byteSwap(T, readIntSliceNative(T, bytes));1295 return @byteSwap(T, readIntSliceNative(T, bytes));
1295}1296}
12961297
1297pub const readIntSliceLittle = switch (builtin.endian) {1298pub const readIntSliceLittle = switch (native_endian) {
1298 .Little => readIntSliceNative,1299 .Little => readIntSliceNative,
1299 .Big => readIntSliceForeign,1300 .Big => readIntSliceForeign,
1300};1301};
13011302
1302pub const readIntSliceBig = switch (builtin.endian) {1303pub const readIntSliceBig = switch (native_endian) {
1303 .Little => readIntSliceForeign,1304 .Little => readIntSliceForeign,
1304 .Big => readIntSliceNative,1305 .Big => readIntSliceNative,
1305};1306};
...@@ -1307,8 +1308,8 @@ pub const readIntSliceBig = switch (builtin.endian) {...@@ -1307,8 +1308,8 @@ pub const readIntSliceBig = switch (builtin.endian) {
1307/// Reads an integer from memory with bit count specified by T.1308/// Reads an integer from memory with bit count specified by T.
1308/// The bit count of T must be evenly divisible by 8.1309/// The bit count of T must be evenly divisible by 8.
1309/// This function cannot fail and cannot cause undefined behavior.1310/// This function cannot fail and cannot cause undefined behavior.
1310pub fn readInt(comptime T: type, bytes: *const [@divExact(@typeInfo(T).Int.bits, 8)]u8, endian: builtin.Endian) T {1311pub fn readInt(comptime T: type, bytes: *const [@divExact(@typeInfo(T).Int.bits, 8)]u8, endian: Endian) T {
1311 if (endian == builtin.endian) {1312 if (endian == native_endian) {
1312 return readIntNative(T, bytes);1313 return readIntNative(T, bytes);
1313 } else {1314 } else {
1314 return readIntForeign(T, bytes);1315 return readIntForeign(T, bytes);
...@@ -1318,7 +1319,7 @@ pub fn readInt(comptime T: type, bytes: *const [@divExact(@typeInfo(T).Int.bits,...@@ -1318,7 +1319,7 @@ pub fn readInt(comptime T: type, bytes: *const [@divExact(@typeInfo(T).Int.bits,
1318/// Asserts that bytes.len >= @typeInfo(T).Int.bits / 8. Reads the integer starting from index 01319/// Asserts that bytes.len >= @typeInfo(T).Int.bits / 8. Reads the integer starting from index 0
1319/// and ignores extra bytes.1320/// and ignores extra bytes.
1320/// The bit count of T must be evenly divisible by 8.1321/// The bit count of T must be evenly divisible by 8.
1321pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {1322pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: Endian) T {
1322 const n = @divExact(@typeInfo(T).Int.bits, 8);1323 const n = @divExact(@typeInfo(T).Int.bits, 8);
1323 assert(bytes.len >= n);1324 assert(bytes.len >= n);
1324 return readInt(T, bytes[0..n], endian);1325 return readInt(T, bytes[0..n], endian);
...@@ -1376,12 +1377,12 @@ pub fn writeIntForeign(comptime T: type, buf: *[@divExact(@typeInfo(T).Int.bits,...@@ -1376,12 +1377,12 @@ pub fn writeIntForeign(comptime T: type, buf: *[@divExact(@typeInfo(T).Int.bits,
1376 writeIntNative(T, buf, @byteSwap(T, value));1377 writeIntNative(T, buf, @byteSwap(T, value));
1377}1378}
13781379
1379pub const writeIntLittle = switch (builtin.endian) {1380pub const writeIntLittle = switch (native_endian) {
1380 .Little => writeIntNative,1381 .Little => writeIntNative,
1381 .Big => writeIntForeign,1382 .Big => writeIntForeign,
1382};1383};
13831384
1384pub const writeIntBig = switch (builtin.endian) {1385pub const writeIntBig = switch (native_endian) {
1385 .Little => writeIntForeign,1386 .Little => writeIntForeign,
1386 .Big => writeIntNative,1387 .Big => writeIntNative,
1387};1388};
...@@ -1389,8 +1390,8 @@ pub const writeIntBig = switch (builtin.endian) {...@@ -1389,8 +1390,8 @@ pub const writeIntBig = switch (builtin.endian) {
1389/// Writes an integer to memory, storing it in twos-complement.1390/// Writes an integer to memory, storing it in twos-complement.
1390/// This function always succeeds, has defined behavior for all inputs, but1391/// This function always succeeds, has defined behavior for all inputs, but
1391/// the integer bit width must be divisible by 8.1392/// the integer bit width must be divisible by 8.
1392pub fn writeInt(comptime T: type, buffer: *[@divExact(@typeInfo(T).Int.bits, 8)]u8, value: T, endian: builtin.Endian) void {1393pub fn writeInt(comptime T: type, buffer: *[@divExact(@typeInfo(T).Int.bits, 8)]u8, value: T, endian: Endian) void {
1393 if (endian == builtin.endian) {1394 if (endian == native_endian) {
1394 return writeIntNative(T, buffer, value);1395 return writeIntNative(T, buffer, value);
1395 } else {1396 } else {
1396 return writeIntForeign(T, buffer, value);1397 return writeIntForeign(T, buffer, value);
...@@ -1440,12 +1441,12 @@ pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {...@@ -1440,12 +1441,12 @@ pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
1440 }1441 }
1441}1442}
14421443
1443pub const writeIntSliceNative = switch (builtin.endian) {1444pub const writeIntSliceNative = switch (native_endian) {
1444 .Little => writeIntSliceLittle,1445 .Little => writeIntSliceLittle,
1445 .Big => writeIntSliceBig,1446 .Big => writeIntSliceBig,
1446};1447};
14471448
1448pub const writeIntSliceForeign = switch (builtin.endian) {1449pub const writeIntSliceForeign = switch (native_endian) {
1449 .Little => writeIntSliceBig,1450 .Little => writeIntSliceBig,
1450 .Big => writeIntSliceLittle,1451 .Big => writeIntSliceLittle,
1451};1452};
...@@ -1456,7 +1457,7 @@ pub const writeIntSliceForeign = switch (builtin.endian) {...@@ -1456,7 +1457,7 @@ pub const writeIntSliceForeign = switch (builtin.endian) {
1456/// Any extra bytes in buffer not part of the integer are set to zero, with1457/// Any extra bytes in buffer not part of the integer are set to zero, with
1457/// respect to endianness. To avoid the branch to check for extra buffer bytes,1458/// respect to endianness. To avoid the branch to check for extra buffer bytes,
1458/// use writeInt instead.1459/// use writeInt instead.
1459pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: builtin.Endian) void {1460pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: Endian) void {
1460 comptime assert(@typeInfo(T).Int.bits % 8 == 0);1461 comptime assert(@typeInfo(T).Int.bits % 8 == 0);
1461 return switch (endian) {1462 return switch (endian) {
1462 .Little => writeIntSliceLittle(T, buffer, value),1463 .Little => writeIntSliceLittle(T, buffer, value),
...@@ -1866,10 +1867,10 @@ fn testReadIntImpl() !void {...@@ -1866,10 +1867,10 @@ fn testReadIntImpl() !void {
1866 0x56,1867 0x56,
1867 0x78,1868 0x78,
1868 };1869 };
1869 try testing.expect(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678);1870 try testing.expect(readInt(u32, &bytes, Endian.Big) == 0x12345678);
1870 try testing.expect(readIntBig(u32, &bytes) == 0x12345678);1871 try testing.expect(readIntBig(u32, &bytes) == 0x12345678);
1871 try testing.expect(readIntBig(i32, &bytes) == 0x12345678);1872 try testing.expect(readIntBig(i32, &bytes) == 0x12345678);
1872 try testing.expect(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412);1873 try testing.expect(readInt(u32, &bytes, Endian.Little) == 0x78563412);
1873 try testing.expect(readIntLittle(u32, &bytes) == 0x78563412);1874 try testing.expect(readIntLittle(u32, &bytes) == 0x78563412);
1874 try testing.expect(readIntLittle(i32, &bytes) == 0x78563412);1875 try testing.expect(readIntLittle(i32, &bytes) == 0x78563412);
1875 }1876 }
...@@ -1880,7 +1881,7 @@ fn testReadIntImpl() !void {...@@ -1880,7 +1881,7 @@ fn testReadIntImpl() !void {
1880 0x12,1881 0x12,
1881 0x34,1882 0x34,
1882 };1883 };
1883 const answer = readInt(u32, &buf, builtin.Endian.Big);1884 const answer = readInt(u32, &buf, Endian.Big);
1884 try testing.expect(answer == 0x00001234);1885 try testing.expect(answer == 0x00001234);
1885 }1886 }
1886 {1887 {
...@@ -1890,7 +1891,7 @@ fn testReadIntImpl() !void {...@@ -1890,7 +1891,7 @@ fn testReadIntImpl() !void {
1890 0x00,1891 0x00,
1891 0x00,1892 0x00,
1892 };1893 };
1893 const answer = readInt(u32, &buf, builtin.Endian.Little);1894 const answer = readInt(u32, &buf, Endian.Little);
1894 try testing.expect(answer == 0x00003412);1895 try testing.expect(answer == 0x00003412);
1895 }1896 }
1896 {1897 {
...@@ -1912,19 +1913,19 @@ test "writeIntSlice" {...@@ -1912,19 +1913,19 @@ test "writeIntSlice" {
1912fn testWriteIntImpl() !void {1913fn testWriteIntImpl() !void {
1913 var bytes: [8]u8 = undefined;1914 var bytes: [8]u8 = undefined;
19141915
1915 writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big);1916 writeIntSlice(u0, bytes[0..], 0, Endian.Big);
1916 try testing.expect(eql(u8, &bytes, &[_]u8{1917 try testing.expect(eql(u8, &bytes, &[_]u8{
1917 0x00, 0x00, 0x00, 0x00,1918 0x00, 0x00, 0x00, 0x00,
1918 0x00, 0x00, 0x00, 0x00,1919 0x00, 0x00, 0x00, 0x00,
1919 }));1920 }));
19201921
1921 writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Little);1922 writeIntSlice(u0, bytes[0..], 0, Endian.Little);
1922 try testing.expect(eql(u8, &bytes, &[_]u8{1923 try testing.expect(eql(u8, &bytes, &[_]u8{
1923 0x00, 0x00, 0x00, 0x00,1924 0x00, 0x00, 0x00, 0x00,
1924 0x00, 0x00, 0x00, 0x00,1925 0x00, 0x00, 0x00, 0x00,
1925 }));1926 }));
19261927
1927 writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, builtin.Endian.Big);1928 writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, Endian.Big);
1928 try testing.expect(eql(u8, &bytes, &[_]u8{1929 try testing.expect(eql(u8, &bytes, &[_]u8{
1929 0x12,1930 0x12,
1930 0x34,1931 0x34,
...@@ -1936,7 +1937,7 @@ fn testWriteIntImpl() !void {...@@ -1936,7 +1937,7 @@ fn testWriteIntImpl() !void {
1936 0xBE,1937 0xBE,
1937 }));1938 }));
19381939
1939 writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little);1940 writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, Endian.Little);
1940 try testing.expect(eql(u8, &bytes, &[_]u8{1941 try testing.expect(eql(u8, &bytes, &[_]u8{
1941 0x12,1942 0x12,
1942 0x34,1943 0x34,
...@@ -1948,7 +1949,7 @@ fn testWriteIntImpl() !void {...@@ -1948,7 +1949,7 @@ fn testWriteIntImpl() !void {
1948 0xBE,1949 0xBE,
1949 }));1950 }));
19501951
1951 writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big);1952 writeIntSlice(u32, bytes[0..], 0x12345678, Endian.Big);
1952 try testing.expect(eql(u8, &bytes, &[_]u8{1953 try testing.expect(eql(u8, &bytes, &[_]u8{
1953 0x00,1954 0x00,
1954 0x00,1955 0x00,
...@@ -1960,7 +1961,7 @@ fn testWriteIntImpl() !void {...@@ -1960,7 +1961,7 @@ fn testWriteIntImpl() !void {
1960 0x78,1961 0x78,
1961 }));1962 }));
19621963
1963 writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little);1964 writeIntSlice(u32, bytes[0..], 0x78563412, Endian.Little);
1964 try testing.expect(eql(u8, &bytes, &[_]u8{1965 try testing.expect(eql(u8, &bytes, &[_]u8{
1965 0x12,1966 0x12,
1966 0x34,1967 0x34,
...@@ -1972,7 +1973,7 @@ fn testWriteIntImpl() !void {...@@ -1972,7 +1973,7 @@ fn testWriteIntImpl() !void {
1972 0x00,1973 0x00,
1973 }));1974 }));
19741975
1975 writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big);1976 writeIntSlice(u16, bytes[0..], 0x1234, Endian.Big);
1976 try testing.expect(eql(u8, &bytes, &[_]u8{1977 try testing.expect(eql(u8, &bytes, &[_]u8{
1977 0x00,1978 0x00,
1978 0x00,1979 0x00,
...@@ -1984,7 +1985,7 @@ fn testWriteIntImpl() !void {...@@ -1984,7 +1985,7 @@ fn testWriteIntImpl() !void {
1984 0x34,1985 0x34,
1985 }));1986 }));
19861987
1987 writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little);1988 writeIntSlice(u16, bytes[0..], 0x1234, Endian.Little);
1988 try testing.expect(eql(u8, &bytes, &[_]u8{1989 try testing.expect(eql(u8, &bytes, &[_]u8{
1989 0x34,1990 0x34,
1990 0x12,1991 0x12,
...@@ -2173,7 +2174,7 @@ test "replaceOwned" {...@@ -2173,7 +2174,7 @@ test "replaceOwned" {
21732174
2174/// Converts a little-endian integer to host endianness.2175/// Converts a little-endian integer to host endianness.
2175pub fn littleToNative(comptime T: type, x: T) T {2176pub fn littleToNative(comptime T: type, x: T) T {
2176 return switch (builtin.endian) {2177 return switch (native_endian) {
2177 .Little => x,2178 .Little => x,
2178 .Big => @byteSwap(T, x),2179 .Big => @byteSwap(T, x),
2179 };2180 };
...@@ -2181,14 +2182,14 @@ pub fn littleToNative(comptime T: type, x: T) T {...@@ -2181,14 +2182,14 @@ pub fn littleToNative(comptime T: type, x: T) T {
21812182
2182/// Converts a big-endian integer to host endianness.2183/// Converts a big-endian integer to host endianness.
2183pub fn bigToNative(comptime T: type, x: T) T {2184pub fn bigToNative(comptime T: type, x: T) T {
2184 return switch (builtin.endian) {2185 return switch (native_endian) {
2185 .Little => @byteSwap(T, x),2186 .Little => @byteSwap(T, x),
2186 .Big => x,2187 .Big => x,
2187 };2188 };
2188}2189}
21892190
2190/// Converts an integer from specified endianness to host endianness.2191/// Converts an integer from specified endianness to host endianness.
2191pub fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T {2192pub fn toNative(comptime T: type, x: T, endianness_of_x: Endian) T {
2192 return switch (endianness_of_x) {2193 return switch (endianness_of_x) {
2193 .Little => littleToNative(T, x),2194 .Little => littleToNative(T, x),
2194 .Big => bigToNative(T, x),2195 .Big => bigToNative(T, x),
...@@ -2196,7 +2197,7 @@ pub fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T {...@@ -2196,7 +2197,7 @@ pub fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T {
2196}2197}
21972198
2198/// Converts an integer which has host endianness to the desired endianness.2199/// Converts an integer which has host endianness to the desired endianness.
2199pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T {2200pub fn nativeTo(comptime T: type, x: T, desired_endianness: Endian) T {
2200 return switch (desired_endianness) {2201 return switch (desired_endianness) {
2201 .Little => nativeToLittle(T, x),2202 .Little => nativeToLittle(T, x),
2202 .Big => nativeToBig(T, x),2203 .Big => nativeToBig(T, x),
...@@ -2205,7 +2206,7 @@ pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T {...@@ -2205,7 +2206,7 @@ pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T {
22052206
2206/// Converts an integer which has host endianness to little endian.2207/// Converts an integer which has host endianness to little endian.
2207pub fn nativeToLittle(comptime T: type, x: T) T {2208pub fn nativeToLittle(comptime T: type, x: T) T {
2208 return switch (builtin.endian) {2209 return switch (native_endian) {
2209 .Little => x,2210 .Little => x,
2210 .Big => @byteSwap(T, x),2211 .Big => @byteSwap(T, x),
2211 };2212 };
...@@ -2213,13 +2214,13 @@ pub fn nativeToLittle(comptime T: type, x: T) T {...@@ -2213,13 +2214,13 @@ pub fn nativeToLittle(comptime T: type, x: T) T {
22132214
2214/// Converts an integer which has host endianness to big endian.2215/// Converts an integer which has host endianness to big endian.
2215pub fn nativeToBig(comptime T: type, x: T) T {2216pub fn nativeToBig(comptime T: type, x: T) T {
2216 return switch (builtin.endian) {2217 return switch (native_endian) {
2217 .Little => @byteSwap(T, x),2218 .Little => @byteSwap(T, x),
2218 .Big => x,2219 .Big => x,
2219 };2220 };
2220}2221}
22212222
2222fn CopyPtrAttrs(comptime source: type, comptime size: builtin.TypeInfo.Pointer.Size, comptime child: type) type {2223fn CopyPtrAttrs(comptime source: type, comptime size: std.builtin.TypeInfo.Pointer.Size, comptime child: type) type {
2223 const info = @typeInfo(source).Pointer;2224 const info = @typeInfo(source).Pointer;
2224 return @Type(.{2225 return @Type(.{
2225 .Pointer = .{2226 .Pointer = .{
...@@ -2251,7 +2252,7 @@ pub fn asBytes(ptr: anytype) AsBytesReturnType(@TypeOf(ptr)) {...@@ -2251,7 +2252,7 @@ pub fn asBytes(ptr: anytype) AsBytesReturnType(@TypeOf(ptr)) {
22512252
2252test "asBytes" {2253test "asBytes" {
2253 const deadbeef = @as(u32, 0xDEADBEEF);2254 const deadbeef = @as(u32, 0xDEADBEEF);
2254 const deadbeef_bytes = switch (builtin.endian) {2255 const deadbeef_bytes = switch (native_endian) {
2255 .Big => "\xDE\xAD\xBE\xEF",2256 .Big => "\xDE\xAD\xBE\xEF",
2256 .Little => "\xEF\xBE\xAD\xDE",2257 .Little => "\xEF\xBE\xAD\xDE",
2257 };2258 };
...@@ -2304,13 +2305,13 @@ pub fn toBytes(value: anytype) [@sizeOf(@TypeOf(value))]u8 {...@@ -2304,13 +2305,13 @@ pub fn toBytes(value: anytype) [@sizeOf(@TypeOf(value))]u8 {
23042305
2305test "toBytes" {2306test "toBytes" {
2306 var my_bytes = toBytes(@as(u32, 0x12345678));2307 var my_bytes = toBytes(@as(u32, 0x12345678));
2307 switch (builtin.endian) {2308 switch (native_endian) {
2308 .Big => try testing.expect(eql(u8, &my_bytes, "\x12\x34\x56\x78")),2309 .Big => try testing.expect(eql(u8, &my_bytes, "\x12\x34\x56\x78")),
2309 .Little => try testing.expect(eql(u8, &my_bytes, "\x78\x56\x34\x12")),2310 .Little => try testing.expect(eql(u8, &my_bytes, "\x78\x56\x34\x12")),
2310 }2311 }
23112312
2312 my_bytes[0] = '\x99';2313 my_bytes[0] = '\x99';
2313 switch (builtin.endian) {2314 switch (native_endian) {
2314 .Big => try testing.expect(eql(u8, &my_bytes, "\x99\x34\x56\x78")),2315 .Big => try testing.expect(eql(u8, &my_bytes, "\x99\x34\x56\x78")),
2315 .Little => try testing.expect(eql(u8, &my_bytes, "\x99\x56\x34\x12")),2316 .Little => try testing.expect(eql(u8, &my_bytes, "\x99\x56\x34\x12")),
2316 }2317 }
...@@ -2337,14 +2338,14 @@ pub fn bytesAsValue(comptime T: type, bytes: anytype) BytesAsValueReturnType(T,...@@ -2337,14 +2338,14 @@ pub fn bytesAsValue(comptime T: type, bytes: anytype) BytesAsValueReturnType(T,
23372338
2338test "bytesAsValue" {2339test "bytesAsValue" {
2339 const deadbeef = @as(u32, 0xDEADBEEF);2340 const deadbeef = @as(u32, 0xDEADBEEF);
2340 const deadbeef_bytes = switch (builtin.endian) {2341 const deadbeef_bytes = switch (native_endian) {
2341 .Big => "\xDE\xAD\xBE\xEF",2342 .Big => "\xDE\xAD\xBE\xEF",
2342 .Little => "\xEF\xBE\xAD\xDE",2343 .Little => "\xEF\xBE\xAD\xDE",
2343 };2344 };
23442345
2345 try testing.expect(deadbeef == bytesAsValue(u32, deadbeef_bytes).*);2346 try testing.expect(deadbeef == bytesAsValue(u32, deadbeef_bytes).*);
23462347
2347 var codeface_bytes: [4]u8 = switch (builtin.endian) {2348 var codeface_bytes: [4]u8 = switch (native_endian) {
2348 .Big => "\xC0\xDE\xFA\xCE",2349 .Big => "\xC0\xDE\xFA\xCE",
2349 .Little => "\xCE\xFA\xDE\xC0",2350 .Little => "\xCE\xFA\xDE\xC0",
2350 }.*;2351 }.*;
...@@ -2392,7 +2393,7 @@ pub fn bytesToValue(comptime T: type, bytes: anytype) T {...@@ -2392,7 +2393,7 @@ pub fn bytesToValue(comptime T: type, bytes: anytype) T {
2392 return bytesAsValue(T, bytes).*;2393 return bytesAsValue(T, bytes).*;
2393}2394}
2394test "bytesToValue" {2395test "bytesToValue" {
2395 const deadbeef_bytes = switch (builtin.endian) {2396 const deadbeef_bytes = switch (native_endian) {
2396 .Big => "\xDE\xAD\xBE\xEF",2397 .Big => "\xDE\xAD\xBE\xEF",
2397 .Little => "\xEF\xBE\xAD\xDE",2398 .Little => "\xEF\xBE\xAD\xDE",
2398 };2399 };
...@@ -2521,7 +2522,7 @@ test "sliceAsBytes" {...@@ -2521,7 +2522,7 @@ test "sliceAsBytes" {
2521 const bytes = [_]u16{ 0xDEAD, 0xBEEF };2522 const bytes = [_]u16{ 0xDEAD, 0xBEEF };
2522 const slice = sliceAsBytes(bytes[0..]);2523 const slice = sliceAsBytes(bytes[0..]);
2523 try testing.expect(slice.len == 4);2524 try testing.expect(slice.len == 4);
2524 try testing.expect(eql(u8, slice, switch (builtin.endian) {2525 try testing.expect(eql(u8, slice, switch (native_endian) {
2525 .Big => "\xDE\xAD\xBE\xEF",2526 .Big => "\xDE\xAD\xBE\xEF",
2526 .Little => "\xAD\xDE\xEF\xBE",2527 .Little => "\xAD\xDE\xEF\xBE",
2527 }));2528 }));
...@@ -2543,7 +2544,7 @@ test "sliceAsBytes packed struct at runtime and comptime" {...@@ -2543,7 +2544,7 @@ test "sliceAsBytes packed struct at runtime and comptime" {
2543 var foo: Foo = undefined;2544 var foo: Foo = undefined;
2544 var slice = sliceAsBytes(@as(*[1]Foo, &foo)[0..1]);2545 var slice = sliceAsBytes(@as(*[1]Foo, &foo)[0..1]);
2545 slice[0] = 0x13;2546 slice[0] = 0x13;
2546 switch (builtin.endian) {2547 switch (native_endian) {
2547 .Big => {2548 .Big => {
2548 try testing.expect(foo.a == 0x1);2549 try testing.expect(foo.a == 0x1);
2549 try testing.expect(foo.b == 0x3);2550 try testing.expect(foo.b == 0x3);
lib/std/meta.zig+3-11
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std.zig");6const std = @import("std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const debug = std.debug;8const debug = std.debug;
9const mem = std.mem;9const mem = std.mem;
10const math = std.math;10const math = std.math;
...@@ -342,12 +342,6 @@ test "std.meta.containerLayout" {...@@ -342,12 +342,6 @@ test "std.meta.containerLayout" {
342 const E1 = enum {342 const E1 = enum {
343 A,343 A,
344 };344 };
345 const E2 = packed enum {
346 A,
347 };
348 const E3 = extern enum {
349 A,
350 };
351 const S1 = struct {};345 const S1 = struct {};
352 const S2 = packed struct {};346 const S2 = packed struct {};
353 const S3 = extern struct {};347 const S3 = extern struct {};
...@@ -362,8 +356,6 @@ test "std.meta.containerLayout" {...@@ -362,8 +356,6 @@ test "std.meta.containerLayout" {
362 };356 };
363357
364 try testing.expect(containerLayout(E1) == .Auto);358 try testing.expect(containerLayout(E1) == .Auto);
365 try testing.expect(containerLayout(E2) == .Packed);
366 try testing.expect(containerLayout(E3) == .Extern);
367 try testing.expect(containerLayout(S1) == .Auto);359 try testing.expect(containerLayout(S1) == .Auto);
368 try testing.expect(containerLayout(S2) == .Packed);360 try testing.expect(containerLayout(S2) == .Packed);
369 try testing.expect(containerLayout(S3) == .Extern);361 try testing.expect(containerLayout(S3) == .Extern);
...@@ -1024,7 +1016,7 @@ test "std.meta.cast" {...@@ -1024,7 +1016,7 @@ test "std.meta.cast" {
10241016
1025 try testing.expectEqual(@intToPtr(?*c_void, 2), cast(?*c_void, @intToPtr(*u8, 2)));1017 try testing.expectEqual(@intToPtr(?*c_void, 2), cast(?*c_void, @intToPtr(*u8, 2)));
10261018
1027 const C_ENUM = extern enum(c_int) {1019 const C_ENUM = enum(c_int) {
1028 A = 0,1020 A = 0,
1029 B,1021 B,
1030 C,1022 C,
...@@ -1107,7 +1099,7 @@ pub fn sizeof(target: anytype) usize {...@@ -1107,7 +1099,7 @@ pub fn sizeof(target: anytype) usize {
1107}1099}
11081100
1109test "sizeof" {1101test "sizeof" {
1110 const E = extern enum(c_int) { One, _ };1102 const E = enum(c_int) { One, _ };
1111 const S = extern struct { a: u32 };1103 const S = extern struct { a: u32 };
11121104
1113 const ptr_size = @sizeOf(*c_void);1105 const ptr_size = @sizeOf(*c_void);
lib/std/meta/trait.zig+2-2
...@@ -483,8 +483,8 @@ pub fn hasDecls(comptime T: type, comptime names: anytype) bool {...@@ -483,8 +483,8 @@ pub fn hasDecls(comptime T: type, comptime names: anytype) bool {
483test "std.meta.trait.hasDecls" {483test "std.meta.trait.hasDecls" {
484 const TestStruct1 = struct {};484 const TestStruct1 = struct {};
485 const TestStruct2 = struct {485 const TestStruct2 = struct {
486 pub var a: u32;486 pub var a: u32 = undefined;
487 pub var b: u32;487 pub var b: u32 = undefined;
488 c: bool,488 c: bool,
489 pub fn useless() void {}489 pub fn useless() void {}
490 };490 };
lib/std/multi_array_list.zig+16-7
...@@ -147,7 +147,7 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -147,7 +147,7 @@ pub fn MultiArrayList(comptime S: type) type {
147147
148 /// Extend the list by 1 element. Allocates more memory as necessary.148 /// Extend the list by 1 element. Allocates more memory as necessary.
149 pub fn append(self: *Self, gpa: *Allocator, elem: S) !void {149 pub fn append(self: *Self, gpa: *Allocator, elem: S) !void {
150 try self.ensureCapacity(gpa, self.len + 1);150 try self.ensureUnusedCapacity(gpa, 1);
151 self.appendAssumeCapacity(elem);151 self.appendAssumeCapacity(elem);
152 }152 }
153153
...@@ -162,7 +162,7 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -162,7 +162,7 @@ pub fn MultiArrayList(comptime S: type) type {
162 /// Adjust the list's length to `new_len`.162 /// Adjust the list's length to `new_len`.
163 /// Does not initialize added items, if any.163 /// Does not initialize added items, if any.
164 pub fn resize(self: *Self, gpa: *Allocator, new_len: usize) !void {164 pub fn resize(self: *Self, gpa: *Allocator, new_len: usize) !void {
165 try self.ensureCapacity(gpa, new_len);165 try self.ensureTotalCapacity(gpa, new_len);
166 self.len = new_len;166 self.len = new_len;
167 }167 }
168168
...@@ -224,10 +224,13 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -224,10 +224,13 @@ pub fn MultiArrayList(comptime S: type) type {
224 self.len = new_len;224 self.len = new_len;
225 }225 }
226226
227 /// Deprecated: call `ensureUnusedCapacity` or `ensureTotalCapacity`.
228 pub const ensureCapacity = ensureTotalCapacity;
229
227 /// Modify the array so that it can hold at least `new_capacity` items.230 /// Modify the array so that it can hold at least `new_capacity` items.
228 /// Implements super-linear growth to achieve amortized O(1) append operations.231 /// Implements super-linear growth to achieve amortized O(1) append operations.
229 /// Invalidates pointers if additional memory is needed.232 /// Invalidates pointers if additional memory is needed.
230 pub fn ensureCapacity(self: *Self, gpa: *Allocator, new_capacity: usize) !void {233 pub fn ensureTotalCapacity(self: *Self, gpa: *Allocator, new_capacity: usize) !void {
231 var better_capacity = self.capacity;234 var better_capacity = self.capacity;
232 if (better_capacity >= new_capacity) return;235 if (better_capacity >= new_capacity) return;
233236
...@@ -239,6 +242,12 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -239,6 +242,12 @@ pub fn MultiArrayList(comptime S: type) type {
239 return self.setCapacity(gpa, better_capacity);242 return self.setCapacity(gpa, better_capacity);
240 }243 }
241244
245 /// Modify the array so that it can hold at least `additional_count` **more** items.
246 /// Invalidates pointers if additional memory is needed.
247 pub fn ensureUnusedCapacity(self: *Self, gpa: *Allocator, additional_count: usize) !void {
248 return self.ensureTotalCapacity(gpa, self.len + additional_count);
249 }
250
242 /// Modify the array so that it can hold exactly `new_capacity` items.251 /// Modify the array so that it can hold exactly `new_capacity` items.
243 /// Invalidates pointers if additional memory is needed.252 /// Invalidates pointers if additional memory is needed.
244 /// `new_capacity` must be greater or equal to `len`.253 /// `new_capacity` must be greater or equal to `len`.
...@@ -305,7 +314,7 @@ test "basic usage" {...@@ -305,7 +314,7 @@ test "basic usage" {
305314
306 try testing.expectEqual(@as(usize, 0), list.items(.a).len);315 try testing.expectEqual(@as(usize, 0), list.items(.a).len);
307316
308 try list.ensureCapacity(ally, 2);317 try list.ensureTotalCapacity(ally, 2);
309318
310 list.appendAssumeCapacity(.{319 list.appendAssumeCapacity(.{
311 .a = 1,320 .a = 1,
...@@ -382,7 +391,7 @@ test "regression test for @reduce bug" {...@@ -382,7 +391,7 @@ test "regression test for @reduce bug" {
382 }){};391 }){};
383 defer list.deinit(ally);392 defer list.deinit(ally);
384393
385 try list.ensureCapacity(ally, 20);394 try list.ensureTotalCapacity(ally, 20);
386395
387 try list.append(ally, .{ .tag = .keyword_const, .start = 0 });396 try list.append(ally, .{ .tag = .keyword_const, .start = 0 });
388 try list.append(ally, .{ .tag = .identifier, .start = 6 });397 try list.append(ally, .{ .tag = .identifier, .start = 6 });
...@@ -462,7 +471,7 @@ test "ensure capacity on empty list" {...@@ -462,7 +471,7 @@ test "ensure capacity on empty list" {
462 var list = MultiArrayList(Foo){};471 var list = MultiArrayList(Foo){};
463 defer list.deinit(ally);472 defer list.deinit(ally);
464473
465 try list.ensureCapacity(ally, 2);474 try list.ensureTotalCapacity(ally, 2);
466 list.appendAssumeCapacity(.{ .a = 1, .b = 2 });475 list.appendAssumeCapacity(.{ .a = 1, .b = 2 });
467 list.appendAssumeCapacity(.{ .a = 3, .b = 4 });476 list.appendAssumeCapacity(.{ .a = 3, .b = 4 });
468477
...@@ -477,7 +486,7 @@ test "ensure capacity on empty list" {...@@ -477,7 +486,7 @@ test "ensure capacity on empty list" {
477 try testing.expectEqualSlices(u8, &[_]u8{ 6, 8 }, list.items(.b));486 try testing.expectEqualSlices(u8, &[_]u8{ 6, 8 }, list.items(.b));
478487
479 list.len = 0;488 list.len = 0;
480 try list.ensureCapacity(ally, 16);489 try list.ensureTotalCapacity(ally, 16);
481490
482 list.appendAssumeCapacity(.{ .a = 9, .b = 10 });491 list.appendAssumeCapacity(.{ .a = 9, .b = 10 });
483 list.appendAssumeCapacity(.{ .a = 11, .b = 12 });492 list.appendAssumeCapacity(.{ .a = 11, .b = 12 });
lib/std/net.zig+8-7
...@@ -11,11 +11,12 @@ const mem = std.mem;...@@ -11,11 +11,12 @@ const mem = std.mem;
11const os = std.os;11const os = std.os;
12const fs = std.fs;12const fs = std.fs;
13const io = std.io;13const io = std.io;
14const native_endian = builtin.target.cpu.arch.endian();
1415
15// Windows 10 added support for unix sockets in build 17063, redstone 4 is the16// Windows 10 added support for unix sockets in build 17063, redstone 4 is the
16// first release to support them.17// first release to support them.
17pub const has_unix_sockets = @hasDecl(os, "sockaddr_un") and18pub const has_unix_sockets = @hasDecl(os, "sockaddr_un") and
18 (builtin.os.tag != .windows or19 (builtin.target.os.tag != .windows or
19 std.Target.current.os.version_range.windows.isAtLeast(.win10_rs4) orelse false);20 std.Target.current.os.version_range.windows.isAtLeast(.win10_rs4) orelse false);
2021
21pub const Address = extern union {22pub const Address = extern union {
...@@ -567,7 +568,7 @@ pub const Ip6Address = extern struct {...@@ -567,7 +568,7 @@ pub const Ip6Address = extern struct {
567 return;568 return;
568 }569 }
569 const big_endian_parts = @ptrCast(*align(1) const [8]u16, &self.sa.addr);570 const big_endian_parts = @ptrCast(*align(1) const [8]u16, &self.sa.addr);
570 const native_endian_parts = switch (builtin.endian) {571 const native_endian_parts = switch (native_endian) {
571 .Big => big_endian_parts.*,572 .Big => big_endian_parts.*,
572 .Little => blk: {573 .Little => blk: {
573 var buf: [8]u16 = undefined;574 var buf: [8]u16 = undefined;
...@@ -673,7 +674,7 @@ pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16)...@@ -673,7 +674,7 @@ pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16)
673pub fn tcpConnectToAddress(address: Address) !Stream {674pub fn tcpConnectToAddress(address: Address) !Stream {
674 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;675 const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0;
675 const sock_flags = os.SOCK_STREAM | nonblock |676 const sock_flags = os.SOCK_STREAM | nonblock |
676 (if (builtin.os.tag == .windows) 0 else os.SOCK_CLOEXEC);677 (if (builtin.target.os.tag == .windows) 0 else os.SOCK_CLOEXEC);
677 const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO_TCP);678 const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO_TCP);
678 errdefer os.closeSocket(sockfd);679 errdefer os.closeSocket(sockfd);
679680
...@@ -704,14 +705,14 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*...@@ -704,14 +705,14 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
704 const arena = &result.arena.allocator;705 const arena = &result.arena.allocator;
705 errdefer result.arena.deinit();706 errdefer result.arena.deinit();
706707
707 if (builtin.os.tag == .windows or builtin.link_libc) {708 if (builtin.target.os.tag == .windows or builtin.link_libc) {
708 const name_c = try std.cstr.addNullByte(allocator, name);709 const name_c = try std.cstr.addNullByte(allocator, name);
709 defer allocator.free(name_c);710 defer allocator.free(name_c);
710711
711 const port_c = try std.fmt.allocPrint(allocator, "{}\x00", .{port});712 const port_c = try std.fmt.allocPrint(allocator, "{}\x00", .{port});
712 defer allocator.free(port_c);713 defer allocator.free(port_c);
713714
714 const sys = if (builtin.os.tag == .windows) os.windows.ws2_32 else os.system;715 const sys = if (builtin.target.os.tag == .windows) os.windows.ws2_32 else os.system;
715 const hints = os.addrinfo{716 const hints = os.addrinfo{
716 .flags = sys.AI_NUMERICSERV,717 .flags = sys.AI_NUMERICSERV,
717 .family = os.AF_UNSPEC,718 .family = os.AF_UNSPEC,
...@@ -724,7 +725,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*...@@ -724,7 +725,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
724 };725 };
725 var res: *os.addrinfo = undefined;726 var res: *os.addrinfo = undefined;
726 const rc = sys.getaddrinfo(name_c.ptr, std.meta.assumeSentinel(port_c.ptr, 0), &hints, &res);727 const rc = sys.getaddrinfo(name_c.ptr, std.meta.assumeSentinel(port_c.ptr, 0), &hints, &res);
727 if (builtin.os.tag == .windows) switch (@intToEnum(os.windows.ws2_32.WinsockError, @intCast(u16, rc))) {728 if (builtin.target.os.tag == .windows) switch (@intToEnum(os.windows.ws2_32.WinsockError, @intCast(u16, rc))) {
728 @intToEnum(os.windows.ws2_32.WinsockError, 0) => {},729 @intToEnum(os.windows.ws2_32.WinsockError, 0) => {},
729 .WSATRY_AGAIN => return error.TemporaryNameServerFailure,730 .WSATRY_AGAIN => return error.TemporaryNameServerFailure,
730 .WSANO_RECOVERY => return error.NameServerFailure,731 .WSANO_RECOVERY => return error.NameServerFailure,
...@@ -782,7 +783,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*...@@ -782,7 +783,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
782783
783 return result;784 return result;
784 }785 }
785 if (builtin.os.tag == .linux) {786 if (builtin.target.os.tag == .linux) {
786 const flags = std.c.AI_NUMERICSERV;787 const flags = std.c.AI_NUMERICSERV;
787 const family = os.AF_UNSPEC;788 const family = os.AF_UNSPEC;
788 var lookup_addrs = std.ArrayList(LookupAddr).init(allocator);789 var lookup_addrs = std.ArrayList(LookupAddr).init(allocator);
lib/std/os.zig+1-1
...@@ -21,7 +21,7 @@...@@ -21,7 +21,7 @@
2121
22const root = @import("root");22const root = @import("root");
23const std = @import("std.zig");23const std = @import("std.zig");
24const builtin = @import("builtin");24const builtin = std.builtin;
25const assert = std.debug.assert;25const assert = std.debug.assert;
26const math = std.math;26const math = std.math;
27const mem = std.mem;27const mem = std.mem;
lib/std/os/bits/darwin.zig+4-4
...@@ -1535,19 +1535,19 @@ pub const rusage = extern struct {...@@ -1535,19 +1535,19 @@ pub const rusage = extern struct {
1535 nivcsw: isize,1535 nivcsw: isize,
1536};1536};
15371537
1538pub const rlimit_resource = extern enum(c_int) {1538pub const rlimit_resource = enum(c_int) {
1539 CPU = 0,1539 CPU = 0,
1540 FSIZE = 1,1540 FSIZE = 1,
1541 DATA = 2,1541 DATA = 2,
1542 STACK = 3,1542 STACK = 3,
1543 CORE = 4,1543 CORE = 4,
1544 AS = 5,
1545 RSS = 5,1544 RSS = 5,
1546 MEMLOCK = 6,1545 MEMLOCK = 6,
1547 NPROC = 7,1546 NPROC = 7,
1548 NOFILE = 8,1547 NOFILE = 8,
1549
1550 _,1548 _,
1549
1550 pub const AS: rlimit_resource = .RSS;
1551};1551};
15521552
1553pub const rlim_t = u64;1553pub const rlim_t = u64;
...@@ -1683,7 +1683,7 @@ pub const TCSANOW = 0; // make change immediate...@@ -1683,7 +1683,7 @@ pub const TCSANOW = 0; // make change immediate
1683pub const TCSADRAIN = 1; // drain output, then change1683pub const TCSADRAIN = 1; // drain output, then change
1684pub const TCSAFLUSH = 2; // drain output, flush input1684pub const TCSAFLUSH = 2; // drain output, flush input
1685pub const TCSASOFT = 0x10; // flag - don't alter h.w. state1685pub const TCSASOFT = 0x10; // flag - don't alter h.w. state
1686pub const TCSA = extern enum(c_uint) {1686pub const TCSA = enum(c_uint) {
1687 NOW,1687 NOW,
1688 DRAIN,1688 DRAIN,
1689 FLUSH,1689 FLUSH,
lib/std/os/bits/dragonfly.zig+3-3
...@@ -735,7 +735,7 @@ pub const Flock = extern struct {...@@ -735,7 +735,7 @@ pub const Flock = extern struct {
735 l_whence: c_short,735 l_whence: c_short,
736};736};
737737
738pub const rlimit_resource = extern enum(c_int) {738pub const rlimit_resource = enum(c_int) {
739 CPU = 0,739 CPU = 0,
740 FSIZE = 1,740 FSIZE = 1,
741 DATA = 2,741 DATA = 2,
...@@ -746,11 +746,11 @@ pub const rlimit_resource = extern enum(c_int) {...@@ -746,11 +746,11 @@ pub const rlimit_resource = extern enum(c_int) {
746 NPROC = 7,746 NPROC = 7,
747 NOFILE = 8,747 NOFILE = 8,
748 SBSIZE = 9,748 SBSIZE = 9,
749 AS = 10,
750 VMEM = 10,749 VMEM = 10,
751 POSIXLOCKS = 11,750 POSIXLOCKS = 11,
752
753 _,751 _,
752
753 pub const AS: rlimit_resource = .VMEM;
754};754};
755755
756pub const rlim_t = i64;756pub const rlim_t = i64;
lib/std/os/bits/freebsd.zig+6-6
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("../../std.zig");6const std = @import("../../std.zig");
7const builtin = std.builtin;7const builtin = @import("builtin");
8const maxInt = std.math.maxInt;8const maxInt = std.math.maxInt;
99
10pub const blksize_t = i32;10pub const blksize_t = i32;
...@@ -842,7 +842,7 @@ pub const sigset_t = extern struct {...@@ -842,7 +842,7 @@ pub const sigset_t = extern struct {
842842
843pub const empty_sigset = sigset_t{ .__bits = [_]u32{0} ** _SIG_WORDS };843pub const empty_sigset = sigset_t{ .__bits = [_]u32{0} ** _SIG_WORDS };
844844
845pub usingnamespace switch (builtin.arch) {845pub usingnamespace switch (builtin.target.cpu.arch) {
846 .x86_64 => struct {846 .x86_64 => struct {
847 pub const ucontext_t = extern struct {847 pub const ucontext_t = extern struct {
848 sigmask: sigset_t,848 sigmask: sigset_t,
...@@ -1011,7 +1011,7 @@ pub const EOWNERDEAD = 96; // Previous owner died...@@ -1011,7 +1011,7 @@ pub const EOWNERDEAD = 96; // Previous owner died
10111011
1012pub const ELAST = 96; // Must be equal largest errno1012pub const ELAST = 96; // Must be equal largest errno
10131013
1014pub const MINSIGSTKSZ = switch (builtin.arch) {1014pub const MINSIGSTKSZ = switch (builtin.target.cpu.arch) {
1015 .i386, .x86_64 => 2048,1015 .i386, .x86_64 => 2048,
1016 .arm, .aarch64 => 4096,1016 .arm, .aarch64 => 4096,
1017 else => @compileError("MINSIGSTKSZ not defined for this architecture"),1017 else => @compileError("MINSIGSTKSZ not defined for this architecture"),
...@@ -1467,7 +1467,7 @@ pub const IPPROTO_RESERVED_253 = 253;...@@ -1467,7 +1467,7 @@ pub const IPPROTO_RESERVED_253 = 253;
1467/// Reserved1467/// Reserved
1468pub const IPPROTO_RESERVED_254 = 254;1468pub const IPPROTO_RESERVED_254 = 254;
14691469
1470pub const rlimit_resource = extern enum(c_int) {1470pub const rlimit_resource = enum(c_int) {
1471 CPU = 0,1471 CPU = 0,
1472 FSIZE = 1,1472 FSIZE = 1,
1473 DATA = 2,1473 DATA = 2,
...@@ -1479,13 +1479,13 @@ pub const rlimit_resource = extern enum(c_int) {...@@ -1479,13 +1479,13 @@ pub const rlimit_resource = extern enum(c_int) {
1479 NOFILE = 8,1479 NOFILE = 8,
1480 SBSIZE = 9,1480 SBSIZE = 9,
1481 VMEM = 10,1481 VMEM = 10,
1482 AS = 10,
1483 NPTS = 11,1482 NPTS = 11,
1484 SWAP = 12,1483 SWAP = 12,
1485 KQUEUES = 13,1484 KQUEUES = 13,
1486 UMTXP = 14,1485 UMTXP = 14,
1487
1488 _,1486 _,
1487
1488 pub const AS: rlimit_resource = .VMEM;
1489};1489};
14901490
1491pub const rlim_t = i64;1491pub const rlim_t = i64;
lib/std/os/bits/haiku.zig+4-4
...@@ -1314,7 +1314,7 @@ pub const IPPROTO_RESERVED_253 = 253;...@@ -1314,7 +1314,7 @@ pub const IPPROTO_RESERVED_253 = 253;
1314/// Reserved1314/// Reserved
1315pub const IPPROTO_RESERVED_254 = 254;1315pub const IPPROTO_RESERVED_254 = 254;
13161316
1317pub const rlimit_resource = extern enum(c_int) {1317pub const rlimit_resource = enum(c_int) {
1318 CPU = 0,1318 CPU = 0,
1319 FSIZE = 1,1319 FSIZE = 1,
1320 DATA = 2,1320 DATA = 2,
...@@ -1326,13 +1326,13 @@ pub const rlimit_resource = extern enum(c_int) {...@@ -1326,13 +1326,13 @@ pub const rlimit_resource = extern enum(c_int) {
1326 NOFILE = 8,1326 NOFILE = 8,
1327 SBSIZE = 9,1327 SBSIZE = 9,
1328 VMEM = 10,1328 VMEM = 10,
1329 AS = 10,
1330 NPTS = 11,1329 NPTS = 11,
1331 SWAP = 12,1330 SWAP = 12,
1332 KQUEUES = 13,1331 KQUEUES = 13,
1333 UMTXP = 14,1332 UMTXP = 14,
1334
1335 _,1333 _,
1334
1335 pub const AS: rlimit_resource = .VMEM;
1336};1336};
13371337
1338pub const rlim_t = i64;1338pub const rlim_t = i64;
...@@ -1355,7 +1355,7 @@ pub const SHUT_WR = 1;...@@ -1355,7 +1355,7 @@ pub const SHUT_WR = 1;
1355pub const SHUT_RDWR = 2;1355pub const SHUT_RDWR = 2;
13561356
1357// TODO fill out if needed1357// TODO fill out if needed
1358pub const directory_which = extern enum(c_int) {1358pub const directory_which = enum(c_int) {
1359 B_USER_SETTINGS_DIRECTORY = 0xbbe,1359 B_USER_SETTINGS_DIRECTORY = 0xbbe,
13601360
1361 _,1361 _,
lib/std/os/bits/linux.zig+21-21
...@@ -3,18 +3,18 @@...@@ -3,18 +3,18 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");
7const std = @import("../../std.zig");6const std = @import("../../std.zig");
8const maxInt = std.math.maxInt;7const maxInt = std.math.maxInt;
8const arch = @import("builtin").target.cpu.arch;
9usingnamespace @import("../bits.zig");9usingnamespace @import("../bits.zig");
1010
11pub usingnamespace switch (builtin.arch) {11pub usingnamespace switch (arch) {
12 .mips, .mipsel => @import("linux/errno-mips.zig"),12 .mips, .mipsel => @import("linux/errno-mips.zig"),
13 .sparc, .sparcel, .sparcv9 => @import("linux/errno-sparc.zig"),13 .sparc, .sparcel, .sparcv9 => @import("linux/errno-sparc.zig"),
14 else => @import("linux/errno-generic.zig"),14 else => @import("linux/errno-generic.zig"),
15};15};
1616
17pub usingnamespace switch (builtin.arch) {17pub usingnamespace switch (arch) {
18 .i386 => @import("linux/i386.zig"),18 .i386 => @import("linux/i386.zig"),
19 .x86_64 => @import("linux/x86_64.zig"),19 .x86_64 => @import("linux/x86_64.zig"),
20 .aarch64 => @import("linux/arm64.zig"),20 .aarch64 => @import("linux/arm64.zig"),
...@@ -31,10 +31,10 @@ pub usingnamespace @import("linux/netlink.zig");...@@ -31,10 +31,10 @@ pub usingnamespace @import("linux/netlink.zig");
31pub usingnamespace @import("linux/prctl.zig");31pub usingnamespace @import("linux/prctl.zig");
32pub usingnamespace @import("linux/securebits.zig");32pub usingnamespace @import("linux/securebits.zig");
3333
34const is_mips = builtin.arch.isMIPS();34const is_mips = arch.isMIPS();
35const is_ppc = builtin.arch.isPPC();35const is_ppc = arch.isPPC();
36const is_ppc64 = builtin.arch.isPPC64();36const is_ppc64 = arch.isPPC64();
37const is_sparc = builtin.arch.isSPARC();37const is_sparc = arch.isSPARC();
3838
39pub const pid_t = i32;39pub const pid_t = i32;
40pub const fd_t = i32;40pub const fd_t = i32;
...@@ -136,7 +136,7 @@ pub const PROT_WRITE = 0x2;...@@ -136,7 +136,7 @@ pub const PROT_WRITE = 0x2;
136pub const PROT_EXEC = 0x4;136pub const PROT_EXEC = 0x4;
137137
138/// page may be used for atomic ops138/// page may be used for atomic ops
139pub const PROT_SEM = switch (builtin.arch) {139pub const PROT_SEM = switch (arch) {
140 // TODO: also xtensa140 // TODO: also xtensa
141 .mips, .mipsel, .mips64, .mips64el => 0x10,141 .mips, .mipsel, .mips64, .mips64el => 0x10,
142 else => 0x8,142 else => 0x8,
...@@ -1074,7 +1074,7 @@ pub const sigset_t = [1024 / 32]u32;...@@ -1074,7 +1074,7 @@ pub const sigset_t = [1024 / 32]u32;
1074pub const all_mask: sigset_t = [_]u32{0xffffffff} ** sigset_t.len;1074pub const all_mask: sigset_t = [_]u32{0xffffffff} ** sigset_t.len;
1075pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;1075pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;
10761076
1077pub const k_sigaction = switch (builtin.arch) {1077pub const k_sigaction = switch (arch) {
1078 .mips, .mipsel => extern struct {1078 .mips, .mipsel => extern struct {
1079 flags: c_uint,1079 flags: c_uint,
1080 handler: ?fn (c_int) callconv(.C) void,1080 handler: ?fn (c_int) callconv(.C) void,
...@@ -1198,7 +1198,7 @@ pub const epoll_data = extern union {...@@ -1198,7 +1198,7 @@ pub const epoll_data = extern union {
11981198
1199// On x86_64 the structure is packed so that it matches the definition of its1199// On x86_64 the structure is packed so that it matches the definition of its
1200// 32bit counterpart1200// 32bit counterpart
1201pub const epoll_event = switch (builtin.arch) {1201pub const epoll_event = switch (arch) {
1202 .x86_64 => packed struct {1202 .x86_64 => packed struct {
1203 events: u32,1203 events: u32,
1204 data: epoll_data,1204 data: epoll_data,
...@@ -1365,12 +1365,12 @@ pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {...@@ -1365,12 +1365,12 @@ pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
1365//#define CPU_ZERO(set) CPU_ZERO_S(sizeof(cpu_set_t),set)1365//#define CPU_ZERO(set) CPU_ZERO_S(sizeof(cpu_set_t),set)
1366//#define CPU_EQUAL(s1,s2) CPU_EQUAL_S(sizeof(cpu_set_t),s1,s2)1366//#define CPU_EQUAL(s1,s2) CPU_EQUAL_S(sizeof(cpu_set_t),s1,s2)
13671367
1368pub const MINSIGSTKSZ = switch (builtin.arch) {1368pub const MINSIGSTKSZ = switch (arch) {
1369 .i386, .x86_64, .arm, .mipsel => 2048,1369 .i386, .x86_64, .arm, .mipsel => 2048,
1370 .aarch64 => 5120,1370 .aarch64 => 5120,
1371 else => @compileError("MINSIGSTKSZ not defined for this architecture"),1371 else => @compileError("MINSIGSTKSZ not defined for this architecture"),
1372};1372};
1373pub const SIGSTKSZ = switch (builtin.arch) {1373pub const SIGSTKSZ = switch (arch) {
1374 .i386, .x86_64, .arm, .mipsel => 8192,1374 .i386, .x86_64, .arm, .mipsel => 8192,
1375 .aarch64 => 16384,1375 .aarch64 => 16384,
1376 else => @compileError("SIGSTKSZ not defined for this architecture"),1376 else => @compileError("SIGSTKSZ not defined for this architecture"),
...@@ -1564,7 +1564,7 @@ pub const io_uring_sqe = extern struct {...@@ -1564,7 +1564,7 @@ pub const io_uring_sqe = extern struct {
1564 __pad2: [2]u64,1564 __pad2: [2]u64,
1565};1565};
15661566
1567pub const IOSQE_BIT = extern enum(u8) {1567pub const IOSQE_BIT = enum(u8) {
1568 FIXED_FILE,1568 FIXED_FILE,
1569 IO_DRAIN,1569 IO_DRAIN,
1570 IO_LINK,1570 IO_LINK,
...@@ -1595,7 +1595,7 @@ pub const IOSQE_ASYNC = 1 << @enumToInt(IOSQE_BIT.ASYNC);...@@ -1595,7 +1595,7 @@ pub const IOSQE_ASYNC = 1 << @enumToInt(IOSQE_BIT.ASYNC);
1595/// select buffer from buf_group1595/// select buffer from buf_group
1596pub const IOSQE_BUFFER_SELECT = 1 << @enumToInt(IOSQE_BIT.BUFFER_SELECT);1596pub const IOSQE_BUFFER_SELECT = 1 << @enumToInt(IOSQE_BIT.BUFFER_SELECT);
15971597
1598pub const IORING_OP = extern enum(u8) {1598pub const IORING_OP = enum(u8) {
1599 NOP,1599 NOP,
1600 READV,1600 READV,
1601 WRITEV,1601 WRITEV,
...@@ -1664,7 +1664,7 @@ pub const IORING_ENTER_GETEVENTS = 1 << 0;...@@ -1664,7 +1664,7 @@ pub const IORING_ENTER_GETEVENTS = 1 << 0;
1664pub const IORING_ENTER_SQ_WAKEUP = 1 << 1;1664pub const IORING_ENTER_SQ_WAKEUP = 1 << 1;
16651665
1666// io_uring_register opcodes and arguments1666// io_uring_register opcodes and arguments
1667pub const IORING_REGISTER = extern enum(u8) {1667pub const IORING_REGISTER = enum(u8) {
1668 REGISTER_BUFFERS,1668 REGISTER_BUFFERS,
1669 UNREGISTER_BUFFERS,1669 UNREGISTER_BUFFERS,
1670 REGISTER_FILES,1670 REGISTER_FILES,
...@@ -1731,7 +1731,7 @@ pub const io_uring_restriction = extern struct {...@@ -1731,7 +1731,7 @@ pub const io_uring_restriction = extern struct {
1731};1731};
17321732
1733/// io_uring_restriction->opcode values1733/// io_uring_restriction->opcode values
1734pub const IORING_RESTRICTION = extern enum(u8) {1734pub const IORING_RESTRICTION = enum(u8) {
1735 /// Allow an io_uring_register(2) opcode1735 /// Allow an io_uring_register(2) opcode
1736 REGISTER_OP = 0,1736 REGISTER_OP = 0,
17371737
...@@ -1986,7 +1986,7 @@ pub const tcp_repair_window = extern struct {...@@ -1986,7 +1986,7 @@ pub const tcp_repair_window = extern struct {
1986 rcv_wup: u32,1986 rcv_wup: u32,
1987};1987};
19881988
1989pub const TcpRepairOption = extern enum {1989pub const TcpRepairOption = enum {
1990 TCP_NO_QUEUE,1990 TCP_NO_QUEUE,
1991 TCP_RECV_QUEUE,1991 TCP_RECV_QUEUE,
1992 TCP_SEND_QUEUE,1992 TCP_SEND_QUEUE,
...@@ -1994,7 +1994,7 @@ pub const TcpRepairOption = extern enum {...@@ -1994,7 +1994,7 @@ pub const TcpRepairOption = extern enum {
1994};1994};
19951995
1996/// why fastopen failed from client perspective1996/// why fastopen failed from client perspective
1997pub const tcp_fastopen_client_fail = extern enum {1997pub const tcp_fastopen_client_fail = enum {
1998 /// catch-all1998 /// catch-all
1999 TFO_STATUS_UNSPEC,1999 TFO_STATUS_UNSPEC,
2000 /// if not in TFO_CLIENT_NO_COOKIE mode2000 /// if not in TFO_CLIENT_NO_COOKIE mode
...@@ -2130,7 +2130,7 @@ pub const B3000000 = 0o0010015;...@@ -2130,7 +2130,7 @@ pub const B3000000 = 0o0010015;
2130pub const B3500000 = 0o0010016;2130pub const B3500000 = 0o0010016;
2131pub const B4000000 = 0o0010017;2131pub const B4000000 = 0o0010017;
21322132
2133pub usingnamespace switch (builtin.arch) {2133pub usingnamespace switch (arch) {
2134 .powerpc, .powerpc64, .powerpc64le => struct {2134 .powerpc, .powerpc64, .powerpc64le => struct {
2135 pub const VINTR = 0;2135 pub const VINTR = 0;
2136 pub const VQUIT = 1;2136 pub const VQUIT = 1;
...@@ -2261,7 +2261,7 @@ pub const NOFLSH = 128;...@@ -2261,7 +2261,7 @@ pub const NOFLSH = 128;
2261pub const TOSTOP = 256;2261pub const TOSTOP = 256;
2262pub const IEXTEN = 32768;2262pub const IEXTEN = 32768;
22632263
2264pub const TCSA = extern enum(c_uint) {2264pub const TCSA = enum(c_uint) {
2265 NOW,2265 NOW,
2266 DRAIN,2266 DRAIN,
2267 FLUSH,2267 FLUSH,
...@@ -2312,7 +2312,7 @@ pub const ifreq = extern struct {...@@ -2312,7 +2312,7 @@ pub const ifreq = extern struct {
2312};2312};
23132313
2314// doc comments copied from musl2314// doc comments copied from musl
2315pub const rlimit_resource = extern enum(c_int) {2315pub const rlimit_resource = enum(c_int) {
2316 /// Per-process CPU limit, in seconds.2316 /// Per-process CPU limit, in seconds.
2317 CPU,2317 CPU,
23182318
lib/std/os/bits/linux/arm-eabi.zig+2-4
...@@ -15,7 +15,7 @@ const uid_t = linux.uid_t;...@@ -15,7 +15,7 @@ const uid_t = linux.uid_t;
15const gid_t = linux.gid_t;15const gid_t = linux.gid_t;
16const pid_t = linux.pid_t;16const pid_t = linux.pid_t;
1717
18pub const SYS = extern enum(usize) {18pub const SYS = enum(usize) {
19 restart_syscall = 0,19 restart_syscall = 0,
20 exit = 1,20 exit = 1,
21 fork = 2,21 fork = 2,
...@@ -242,7 +242,6 @@ pub const SYS = extern enum(usize) {...@@ -242,7 +242,6 @@ pub const SYS = extern enum(usize) {
242 tgkill = 268,242 tgkill = 268,
243 utimes = 269,243 utimes = 269,
244 fadvise64_64 = 270,244 fadvise64_64 = 270,
245 arm_fadvise64_64 = 270,
246 pciconfig_iobase = 271,245 pciconfig_iobase = 271,
247 pciconfig_read = 272,246 pciconfig_read = 272,
248 pciconfig_write = 273,247 pciconfig_write = 273,
...@@ -313,8 +312,7 @@ pub const SYS = extern enum(usize) {...@@ -313,8 +312,7 @@ pub const SYS = extern enum(usize) {
313 set_robust_list = 338,312 set_robust_list = 338,
314 get_robust_list = 339,313 get_robust_list = 339,
315 splice = 340,314 splice = 340,
316 sync_file_range2 = 341,315 sync_file_range = 341,
317 arm_sync_file_range = 341,
318 tee = 342,316 tee = 342,
319 vmsplice = 343,317 vmsplice = 343,
320 move_pages = 344,318 move_pages = 344,
lib/std/os/bits/linux/arm64.zig+1-2
...@@ -17,7 +17,7 @@ const gid_t = linux.gid_t;...@@ -17,7 +17,7 @@ const gid_t = linux.gid_t;
17const pid_t = linux.pid_t;17const pid_t = linux.pid_t;
18const stack_t = linux.stack_t;18const stack_t = linux.stack_t;
19const sigset_t = linux.sigset_t;19const sigset_t = linux.sigset_t;
20pub const SYS = extern enum(usize) {20pub const SYS = enum(usize) {
21 io_setup = 0,21 io_setup = 0,
22 io_destroy = 1,22 io_destroy = 1,
23 io_submit = 2,23 io_submit = 2,
...@@ -102,7 +102,6 @@ pub const SYS = extern enum(usize) {...@@ -102,7 +102,6 @@ pub const SYS = extern enum(usize) {
102 sync = 81,102 sync = 81,
103 fsync = 82,103 fsync = 82,
104 fdatasync = 83,104 fdatasync = 83,
105 sync_file_range2 = 84,
106 sync_file_range = 84,105 sync_file_range = 84,
107 timerfd_create = 85,106 timerfd_create = 85,
108 timerfd_settime = 86,107 timerfd_settime = 86,
lib/std/os/bits/linux/i386.zig+1-1
...@@ -17,7 +17,7 @@ const pid_t = linux.pid_t;...@@ -17,7 +17,7 @@ const pid_t = linux.pid_t;
17const stack_t = linux.stack_t;17const stack_t = linux.stack_t;
18const sigset_t = linux.sigset_t;18const sigset_t = linux.sigset_t;
1919
20pub const SYS = extern enum(usize) {20pub const SYS = enum(usize) {
21 restart_syscall = 0,21 restart_syscall = 0,
22 exit = 1,22 exit = 1,
23 fork = 2,23 fork = 2,
lib/std/os/bits/linux/mips.zig+1-1
...@@ -12,7 +12,7 @@ const uid_t = linux.uid_t;...@@ -12,7 +12,7 @@ const uid_t = linux.uid_t;
12const gid_t = linux.gid_t;12const gid_t = linux.gid_t;
13const pid_t = linux.pid_t;13const pid_t = linux.pid_t;
1414
15pub const SYS = extern enum(usize) {15pub const SYS = enum(usize) {
16 pub const Linux = 4000;16 pub const Linux = 4000;
1717
18 syscall = Linux + 0,18 syscall = Linux + 0,
lib/std/os/bits/linux/netlink.zig+5-4
...@@ -126,7 +126,7 @@ pub const NLM_F_CAPPED = 0x100;...@@ -126,7 +126,7 @@ pub const NLM_F_CAPPED = 0x100;
126/// extended ACK TVLs were included126/// extended ACK TVLs were included
127pub const NLM_F_ACK_TLVS = 0x200;127pub const NLM_F_ACK_TLVS = 0x200;
128128
129pub const NetlinkMessageType = extern enum(u16) {129pub const NetlinkMessageType = enum(u16) {
130 /// < 0x10: reserved control messages130 /// < 0x10: reserved control messages
131 pub const MIN_TYPE = 0x10;131 pub const MIN_TYPE = 0x10;
132132
...@@ -287,7 +287,7 @@ pub const rtattr = extern struct {...@@ -287,7 +287,7 @@ pub const rtattr = extern struct {
287 pub const ALIGNTO = 4;287 pub const ALIGNTO = 4;
288};288};
289289
290pub const IFLA = extern enum(c_ushort) {290pub const IFLA = enum(c_ushort) {
291 UNSPEC,291 UNSPEC,
292 ADDRESS,292 ADDRESS,
293 BROADCAST,293 BROADCAST,
...@@ -351,8 +351,7 @@ pub const IFLA = extern enum(c_ushort) {...@@ -351,8 +351,7 @@ pub const IFLA = extern enum(c_ushort) {
351 EVENT,351 EVENT,
352352
353 NEW_NETNSID,353 NEW_NETNSID,
354 IF_NETNSID = 46,354 IF_NETNSID,
355 TARGET_NETNSID = 46, // new alias
356355
357 CARRIER_UP_COUNT,356 CARRIER_UP_COUNT,
358 CARRIER_DOWN_COUNT,357 CARRIER_DOWN_COUNT,
...@@ -361,6 +360,8 @@ pub const IFLA = extern enum(c_ushort) {...@@ -361,6 +360,8 @@ pub const IFLA = extern enum(c_ushort) {
361 MAX_MTU,360 MAX_MTU,
362361
363 _,362 _,
363
364 pub const TARGET_NETNSID: IFLA = .IF_NETNSID;
364};365};
365366
366pub const rtnl_link_ifmap = extern struct {367pub const rtnl_link_ifmap = extern struct {
lib/std/os/bits/linux/powerpc.zig+2-2
...@@ -14,7 +14,7 @@ const gid_t = linux.gid_t;...@@ -14,7 +14,7 @@ const gid_t = linux.gid_t;
14const pid_t = linux.pid_t;14const pid_t = linux.pid_t;
15const stack_t = linux.stack_t;15const stack_t = linux.stack_t;
16const sigset_t = linux.sigset_t;16const sigset_t = linux.sigset_t;
17pub const SYS = extern enum(usize) {17pub const SYS = enum(usize) {
18 restart_syscall = 0,18 restart_syscall = 0,
19 exit = 1,19 exit = 1,
20 fork = 2,20 fork = 2,
...@@ -321,7 +321,7 @@ pub const SYS = extern enum(usize) {...@@ -321,7 +321,7 @@ pub const SYS = extern enum(usize) {
321 signalfd = 305,321 signalfd = 305,
322 timerfd_create = 306,322 timerfd_create = 306,
323 eventfd = 307,323 eventfd = 307,
324 sync_file_range2 = 308,324 sync_file_range = 308,
325 fallocate = 309,325 fallocate = 309,
326 subpage_prot = 310,326 subpage_prot = 310,
327 timerfd_settime = 311,327 timerfd_settime = 311,
lib/std/os/bits/linux/powerpc64.zig+3-3
...@@ -14,7 +14,7 @@ const gid_t = linux.gid_t;...@@ -14,7 +14,7 @@ const gid_t = linux.gid_t;
14const pid_t = linux.pid_t;14const pid_t = linux.pid_t;
15const stack_t = linux.stack_t;15const stack_t = linux.stack_t;
16const sigset_t = linux.sigset_t;16const sigset_t = linux.sigset_t;
17pub const SYS = extern enum(usize) {17pub const SYS = enum(usize) {
18 restart_syscall = 0,18 restart_syscall = 0,
19 exit = 1,19 exit = 1,
20 fork = 2,20 fork = 2,
...@@ -295,7 +295,7 @@ pub const SYS = extern enum(usize) {...@@ -295,7 +295,7 @@ pub const SYS = extern enum(usize) {
295 mknodat = 288,295 mknodat = 288,
296 fchownat = 289,296 fchownat = 289,
297 futimesat = 290,297 futimesat = 290,
298 newfstatat = 291,298 fstatat = 291,
299 unlinkat = 292,299 unlinkat = 292,
300 renameat = 293,300 renameat = 293,
301 linkat = 294,301 linkat = 294,
...@@ -312,7 +312,7 @@ pub const SYS = extern enum(usize) {...@@ -312,7 +312,7 @@ pub const SYS = extern enum(usize) {
312 signalfd = 305,312 signalfd = 305,
313 timerfd_create = 306,313 timerfd_create = 306,
314 eventfd = 307,314 eventfd = 307,
315 sync_file_range2 = 308,315 sync_file_range = 308,
316 fallocate = 309,316 fallocate = 309,
317 subpage_prot = 310,317 subpage_prot = 310,
318 timerfd_settime = 311,318 timerfd_settime = 311,
lib/std/os/bits/linux/prctl.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
66
7pub const PR = extern enum(i32) {7pub const PR = enum(i32) {
8 SET_PDEATHSIG = 1,8 SET_PDEATHSIG = 1,
9 GET_PDEATHSIG = 2,9 GET_PDEATHSIG = 2,
1010
lib/std/os/bits/linux/riscv64.zig+1-1
...@@ -9,7 +9,7 @@ const uid_t = std.os.linux.uid_t;...@@ -9,7 +9,7 @@ const uid_t = std.os.linux.uid_t;
9const gid_t = std.os.linux.gid_t;9const gid_t = std.os.linux.gid_t;
10const pid_t = std.os.linux.pid_t;10const pid_t = std.os.linux.pid_t;
1111
12pub const SYS = extern enum(usize) {12pub const SYS = enum(usize) {
13 pub const arch_specific_syscall = 244;13 pub const arch_specific_syscall = 244;
1414
15 io_setup = 0,15 io_setup = 0,
lib/std/os/bits/linux/sparc64.zig+1-1
...@@ -12,7 +12,7 @@ const socklen_t = linux.socklen_t;...@@ -12,7 +12,7 @@ const socklen_t = linux.socklen_t;
12const iovec = linux.iovec;12const iovec = linux.iovec;
13const iovec_const = linux.iovec_const;13const iovec_const = linux.iovec_const;
1414
15pub const SYS = extern enum(usize) {15pub const SYS = enum(usize) {
16 restart_syscall = 0,16 restart_syscall = 0,
17 exit = 1,17 exit = 1,
18 fork = 2,18 fork = 2,
lib/std/os/bits/linux/x86_64.zig+1-2
...@@ -21,7 +21,7 @@ const iovec_const = linux.iovec_const;...@@ -21,7 +21,7 @@ const iovec_const = linux.iovec_const;
21pub const mode_t = usize;21pub const mode_t = usize;
22pub const time_t = isize;22pub const time_t = isize;
2323
24pub const SYS = extern enum(usize) {24pub const SYS = enum(usize) {
25 read = 0,25 read = 0,
26 write = 1,26 write = 1,
27 open = 2,27 open = 2,
...@@ -284,7 +284,6 @@ pub const SYS = extern enum(usize) {...@@ -284,7 +284,6 @@ pub const SYS = extern enum(usize) {
284 mknodat = 259,284 mknodat = 259,
285 fchownat = 260,285 fchownat = 260,
286 futimesat = 261,286 futimesat = 261,
287 newfstatat = 262,
288 fstatat = 262,287 fstatat = 262,
289 unlinkat = 263,288 unlinkat = 263,
290 renameat = 264,289 renameat = 264,
lib/std/os/bits/netbsd.zig+4-4
...@@ -60,7 +60,7 @@ pub const addrinfo = extern struct {...@@ -60,7 +60,7 @@ pub const addrinfo = extern struct {
60 next: ?*addrinfo,60 next: ?*addrinfo,
61};61};
6262
63pub const EAI = extern enum(c_int) {63pub const EAI = enum(c_int) {
64 /// address family for hostname not supported64 /// address family for hostname not supported
65 ADDRFAMILY = 1,65 ADDRFAMILY = 1,
6666
...@@ -1187,7 +1187,7 @@ pub const IPPROTO_PFSYNC = 240;...@@ -1187,7 +1187,7 @@ pub const IPPROTO_PFSYNC = 240;
1187/// raw IP packet1187/// raw IP packet
1188pub const IPPROTO_RAW = 255;1188pub const IPPROTO_RAW = 255;
11891189
1190pub const rlimit_resource = extern enum(c_int) {1190pub const rlimit_resource = enum(c_int) {
1191 CPU = 0,1191 CPU = 0,
1192 FSIZE = 1,1192 FSIZE = 1,
1193 DATA = 2,1193 DATA = 2,
...@@ -1198,11 +1198,11 @@ pub const rlimit_resource = extern enum(c_int) {...@@ -1198,11 +1198,11 @@ pub const rlimit_resource = extern enum(c_int) {
1198 NPROC = 7,1198 NPROC = 7,
1199 NOFILE = 8,1199 NOFILE = 8,
1200 SBSIZE = 9,1200 SBSIZE = 9,
1201 AS = 10,
1202 VMEM = 10,1201 VMEM = 10,
1203 NTHR = 11,1202 NTHR = 11,
1204
1205 _,1203 _,
1204
1205 pub const AS: rlimit_resource = .VMEM;
1206};1206};
12071207
1208pub const rlim_t = u64;1208pub const rlim_t = u64;
lib/std/os/bits/openbsd.zig+2-2
...@@ -76,7 +76,7 @@ pub const addrinfo = extern struct {...@@ -76,7 +76,7 @@ pub const addrinfo = extern struct {
76 next: ?*addrinfo,76 next: ?*addrinfo,
77};77};
7878
79pub const EAI = extern enum(c_int) {79pub const EAI = enum(c_int) {
80 /// address family for hostname not supported80 /// address family for hostname not supported
81 ADDRFAMILY = -9,81 ADDRFAMILY = -9,
8282
...@@ -1176,7 +1176,7 @@ pub const IPPROTO_PFSYNC = 240;...@@ -1176,7 +1176,7 @@ pub const IPPROTO_PFSYNC = 240;
1176/// raw IP packet1176/// raw IP packet
1177pub const IPPROTO_RAW = 255;1177pub const IPPROTO_RAW = 255;
11781178
1179pub const rlimit_resource = extern enum(c_int) {1179pub const rlimit_resource = enum(c_int) {
1180 CPU,1180 CPU,
1181 FSIZE,1181 FSIZE,
1182 DATA,1182 DATA,
lib/std/os/darwin.zig-1
...@@ -3,7 +3,6 @@...@@ -3,7 +3,6 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");
7const std = @import("../std.zig");6const std = @import("../std.zig");
8pub usingnamespace std.c;7pub usingnamespace std.c;
9pub usingnamespace @import("bits.zig");8pub usingnamespace @import("bits.zig");
lib/std/os/linux.zig+24-25
...@@ -11,14 +11,15 @@...@@ -11,14 +11,15 @@
11// provide `rename` when only the `renameat` syscall exists.11// provide `rename` when only the `renameat` syscall exists.
12// * Does not support POSIX thread cancellation.12// * Does not support POSIX thread cancellation.
13const std = @import("../std.zig");13const std = @import("../std.zig");
14const builtin = std.builtin;
15const assert = std.debug.assert;14const assert = std.debug.assert;
16const maxInt = std.math.maxInt;15const maxInt = std.math.maxInt;
17const elf = std.elf;16const elf = std.elf;
18const vdso = @import("linux/vdso.zig");17const vdso = @import("linux/vdso.zig");
19const dl = @import("../dynamic_library.zig");18const dl = @import("../dynamic_library.zig");
19const native_arch = std.Target.current.cpu.arch;
20const native_endian = native_arch.endian();
2021
21pub usingnamespace switch (builtin.arch) {22pub usingnamespace switch (native_arch) {
22 .i386 => @import("linux/i386.zig"),23 .i386 => @import("linux/i386.zig"),
23 .x86_64 => @import("linux/x86_64.zig"),24 .x86_64 => @import("linux/x86_64.zig"),
24 .aarch64 => @import("linux/arm64.zig"),25 .aarch64 => @import("linux/arm64.zig"),
...@@ -75,7 +76,7 @@ fn splitValueBE64(val: i64) [2]u32 {...@@ -75,7 +76,7 @@ fn splitValueBE64(val: i64) [2]u32 {
75}76}
76fn splitValue64(val: i64) [2]u32 {77fn splitValue64(val: i64) [2]u32 {
77 const u = @bitCast(u64, val);78 const u = @bitCast(u64, val);
78 switch (builtin.endian) {79 switch (native_endian) {
79 .Little => return [2]u32{80 .Little => return [2]u32{
80 @truncate(u32, u),81 @truncate(u32, u),
81 @truncate(u32, u >> 32),82 @truncate(u32, u >> 32),
...@@ -130,7 +131,7 @@ pub fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*:...@@ -130,7 +131,7 @@ pub fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*:
130}131}
131132
132pub fn fork() usize {133pub fn fork() usize {
133 if (comptime builtin.arch.isSPARC()) {134 if (comptime native_arch.isSPARC()) {
134 return syscall_fork();135 return syscall_fork();
135 } else if (@hasField(SYS, "fork")) {136 } else if (@hasField(SYS, "fork")) {
136 return syscall0(.fork);137 return syscall0(.fork);
...@@ -450,7 +451,7 @@ pub fn faccessat(dirfd: i32, path: [*:0]const u8, mode: u32, flags: u32) usize {...@@ -450,7 +451,7 @@ pub fn faccessat(dirfd: i32, path: [*:0]const u8, mode: u32, flags: u32) usize {
450}451}
451452
452pub fn pipe(fd: *[2]i32) usize {453pub fn pipe(fd: *[2]i32) usize {
453 if (comptime (builtin.arch.isMIPS() or builtin.arch.isSPARC())) {454 if (comptime (native_arch.isMIPS() or native_arch.isSPARC())) {
454 return syscall_pipe(fd);455 return syscall_pipe(fd);
455 } else if (@hasField(SYS, "pipe")) {456 } else if (@hasField(SYS, "pipe")) {
456 return syscall1(.pipe, @ptrToInt(fd));457 return syscall1(.pipe, @ptrToInt(fd));
...@@ -933,7 +934,7 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact...@@ -933,7 +934,7 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact
933 const ksa_arg = if (act != null) @ptrToInt(&ksa) else 0;934 const ksa_arg = if (act != null) @ptrToInt(&ksa) else 0;
934 const oldksa_arg = if (oact != null) @ptrToInt(&oldksa) else 0;935 const oldksa_arg = if (oact != null) @ptrToInt(&oldksa) else 0;
935936
936 const result = switch (builtin.arch) {937 const result = switch (native_arch) {
937 // The sparc version of rt_sigaction needs the restorer function to be passed as an argument too.938 // The sparc version of rt_sigaction needs the restorer function to be passed as an argument too.
938 .sparc, .sparcv9 => syscall5(.rt_sigaction, sig, ksa_arg, oldksa_arg, @ptrToInt(ksa.restorer), mask_size),939 .sparc, .sparcv9 => syscall5(.rt_sigaction, sig, ksa_arg, oldksa_arg, @ptrToInt(ksa.restorer), mask_size),
939 else => syscall4(.rt_sigaction, sig, ksa_arg, oldksa_arg, mask_size),940 else => syscall4(.rt_sigaction, sig, ksa_arg, oldksa_arg, mask_size),
...@@ -965,42 +966,42 @@ pub fn sigismember(set: *const sigset_t, sig: u6) bool {...@@ -965,42 +966,42 @@ pub fn sigismember(set: *const sigset_t, sig: u6) bool {
965}966}
966967
967pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {968pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
968 if (builtin.arch == .i386) {969 if (native_arch == .i386) {
969 return socketcall(SC_getsockname, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len) });970 return socketcall(SC_getsockname, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len) });
970 }971 }
971 return syscall3(.getsockname, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len));972 return syscall3(.getsockname, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len));
972}973}
973974
974pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {975pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
975 if (builtin.arch == .i386) {976 if (native_arch == .i386) {
976 return socketcall(SC_getpeername, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len) });977 return socketcall(SC_getpeername, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len) });
977 }978 }
978 return syscall3(.getpeername, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len));979 return syscall3(.getpeername, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len));
979}980}
980981
981pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {982pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
982 if (builtin.arch == .i386) {983 if (native_arch == .i386) {
983 return socketcall(SC_socket, &[3]usize{ domain, socket_type, protocol });984 return socketcall(SC_socket, &[3]usize{ domain, socket_type, protocol });
984 }985 }
985 return syscall3(.socket, domain, socket_type, protocol);986 return syscall3(.socket, domain, socket_type, protocol);
986}987}
987988
988pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {989pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {
989 if (builtin.arch == .i386) {990 if (native_arch == .i386) {
990 return socketcall(SC_setsockopt, &[5]usize{ @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen) });991 return socketcall(SC_setsockopt, &[5]usize{ @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen) });
991 }992 }
992 return syscall5(.setsockopt, @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen));993 return syscall5(.setsockopt, @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen));
993}994}
994995
995pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {996pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {
996 if (builtin.arch == .i386) {997 if (native_arch == .i386) {
997 return socketcall(SC_getsockopt, &[5]usize{ @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen) });998 return socketcall(SC_getsockopt, &[5]usize{ @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen) });
998 }999 }
999 return syscall5(.getsockopt, @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));1000 return syscall5(.getsockopt, @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
1000}1001}
10011002
1002pub fn sendmsg(fd: i32, msg: *const msghdr_const, flags: u32) usize {1003pub fn sendmsg(fd: i32, msg: *const msghdr_const, flags: u32) usize {
1003 if (builtin.arch == .i386) {1004 if (native_arch == .i386) {
1004 return socketcall(SC_sendmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags });1005 return socketcall(SC_sendmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags });
1005 }1006 }
1006 return syscall3(.sendmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags);1007 return syscall3(.sendmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags);
...@@ -1047,49 +1048,49 @@ pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize...@@ -1047,49 +1048,49 @@ pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize
1047}1048}
10481049
1049pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {1050pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
1050 if (builtin.arch == .i386) {1051 if (native_arch == .i386) {
1051 return socketcall(SC_connect, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), len });1052 return socketcall(SC_connect, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), len });
1052 }1053 }
1053 return syscall3(.connect, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), len);1054 return syscall3(.connect, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), len);
1054}1055}
10551056
1056pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {1057pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
1057 if (builtin.arch == .i386) {1058 if (native_arch == .i386) {
1058 return socketcall(SC_recvmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags });1059 return socketcall(SC_recvmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags });
1059 }1060 }
1060 return syscall3(.recvmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags);1061 return syscall3(.recvmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags);
1061}1062}
10621063
1063pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {1064pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {
1064 if (builtin.arch == .i386) {1065 if (native_arch == .i386) {
1065 return socketcall(SC_recvfrom, &[6]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen) });1066 return socketcall(SC_recvfrom, &[6]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen) });
1066 }1067 }
1067 return syscall6(.recvfrom, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));1068 return syscall6(.recvfrom, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
1068}1069}
10691070
1070pub fn shutdown(fd: i32, how: i32) usize {1071pub fn shutdown(fd: i32, how: i32) usize {
1071 if (builtin.arch == .i386) {1072 if (native_arch == .i386) {
1072 return socketcall(SC_shutdown, &[2]usize{ @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, how)) });1073 return socketcall(SC_shutdown, &[2]usize{ @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, how)) });
1073 }1074 }
1074 return syscall2(.shutdown, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, how)));1075 return syscall2(.shutdown, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, how)));
1075}1076}
10761077
1077pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {1078pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
1078 if (builtin.arch == .i386) {1079 if (native_arch == .i386) {
1079 return socketcall(SC_bind, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @intCast(usize, len) });1080 return socketcall(SC_bind, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @intCast(usize, len) });
1080 }1081 }
1081 return syscall3(.bind, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @intCast(usize, len));1082 return syscall3(.bind, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @intCast(usize, len));
1082}1083}
10831084
1084pub fn listen(fd: i32, backlog: u32) usize {1085pub fn listen(fd: i32, backlog: u32) usize {
1085 if (builtin.arch == .i386) {1086 if (native_arch == .i386) {
1086 return socketcall(SC_listen, &[2]usize{ @bitCast(usize, @as(isize, fd)), backlog });1087 return socketcall(SC_listen, &[2]usize{ @bitCast(usize, @as(isize, fd)), backlog });
1087 }1088 }
1088 return syscall2(.listen, @bitCast(usize, @as(isize, fd)), backlog);1089 return syscall2(.listen, @bitCast(usize, @as(isize, fd)), backlog);
1089}1090}
10901091
1091pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {1092pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {
1092 if (builtin.arch == .i386) {1093 if (native_arch == .i386) {
1093 return socketcall(SC_sendto, &[6]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen) });1094 return socketcall(SC_sendto, &[6]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen) });
1094 }1095 }
1095 return syscall6(.sendto, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));1096 return syscall6(.sendto, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));
...@@ -1116,21 +1117,21 @@ pub fn sendfile(outfd: i32, infd: i32, offset: ?*i64, count: usize) usize {...@@ -1116,21 +1117,21 @@ pub fn sendfile(outfd: i32, infd: i32, offset: ?*i64, count: usize) usize {
1116}1117}
11171118
1118pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize {1119pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize {
1119 if (builtin.arch == .i386) {1120 if (native_arch == .i386) {
1120 return socketcall(SC_socketpair, &[4]usize{ @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0]) });1121 return socketcall(SC_socketpair, &[4]usize{ @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0]) });
1121 }1122 }
1122 return syscall4(.socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0]));1123 return syscall4(.socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0]));
1123}1124}
11241125
1125pub fn accept(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t) usize {1126pub fn accept(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t) usize {
1126 if (builtin.arch == .i386) {1127 if (native_arch == .i386) {
1127 return socketcall(SC_accept, &[4]usize{ fd, addr, len, 0 });1128 return socketcall(SC_accept, &[4]usize{ fd, addr, len, 0 });
1128 }1129 }
1129 return accept4(fd, addr, len, 0);1130 return accept4(fd, addr, len, 0);
1130}1131}
11311132
1132pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flags: u32) usize {1133pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flags: u32) usize {
1133 if (builtin.arch == .i386) {1134 if (native_arch == .i386) {
1134 return socketcall(SC_accept4, &[4]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len), flags });1135 return socketcall(SC_accept4, &[4]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len), flags });
1135 }1136 }
1136 return syscall4(.accept4, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len), flags);1137 return syscall4(.accept4, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len), flags);
...@@ -1163,8 +1164,6 @@ pub fn lstat(pathname: [*:0]const u8, statbuf: *kernel_stat) usize {...@@ -1163,8 +1164,6 @@ pub fn lstat(pathname: [*:0]const u8, statbuf: *kernel_stat) usize {
1163pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *kernel_stat, flags: u32) usize {1164pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *kernel_stat, flags: u32) usize {
1164 if (@hasField(SYS, "fstatat64")) {1165 if (@hasField(SYS, "fstatat64")) {
1165 return syscall4(.fstatat64, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);1166 return syscall4(.fstatat64, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);
1166 } else if (@hasField(SYS, "newfstatat")) {
1167 return syscall4(.newfstatat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);
1168 } else {1167 } else {
1169 return syscall4(.fstatat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);1168 return syscall4(.fstatat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);
1170 }1169 }
...@@ -1456,7 +1455,7 @@ pub fn process_vm_writev(pid: pid_t, local: [*]const iovec, local_count: usize,...@@ -1456,7 +1455,7 @@ pub fn process_vm_writev(pid: pid_t, local: [*]const iovec, local_count: usize,
1456}1455}
14571456
1458test {1457test {
1459 if (builtin.os.tag == .linux) {1458 if (std.Target.current.os.tag == .linux) {
1460 _ = @import("linux/test.zig");1459 _ = @import("linux/test.zig");
1461 }1460 }
1462}1461}
lib/std/os/linux/bpf.zig+10-10
...@@ -398,10 +398,10 @@ pub const Insn = packed struct {...@@ -398,10 +398,10 @@ pub const Insn = packed struct {
398398
399 /// r0 - r9 are general purpose 64-bit registers, r10 points to the stack399 /// r0 - r9 are general purpose 64-bit registers, r10 points to the stack
400 /// frame400 /// frame
401 pub const Reg = packed enum(u4) { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 };401 pub const Reg = enum(u4) { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 };
402 const Source = packed enum(u1) { reg, imm };402 const Source = enum(u1) { reg, imm };
403403
404 const Mode = packed enum(u8) {404 const Mode = enum(u8) {
405 imm = IMM,405 imm = IMM,
406 abs = ABS,406 abs = ABS,
407 ind = IND,407 ind = IND,
...@@ -410,7 +410,7 @@ pub const Insn = packed struct {...@@ -410,7 +410,7 @@ pub const Insn = packed struct {
410 msh = MSH,410 msh = MSH,
411 };411 };
412412
413 const AluOp = packed enum(u8) {413 const AluOp = enum(u8) {
414 add = ADD,414 add = ADD,
415 sub = SUB,415 sub = SUB,
416 mul = MUL,416 mul = MUL,
...@@ -426,14 +426,14 @@ pub const Insn = packed struct {...@@ -426,14 +426,14 @@ pub const Insn = packed struct {
426 arsh = ARSH,426 arsh = ARSH,
427 };427 };
428428
429 pub const Size = packed enum(u8) {429 pub const Size = enum(u8) {
430 byte = B,430 byte = B,
431 half_word = H,431 half_word = H,
432 word = W,432 word = W,
433 double_word = DW,433 double_word = DW,
434 };434 };
435435
436 const JmpOp = packed enum(u8) {436 const JmpOp = enum(u8) {
437 ja = JA,437 ja = JA,
438 jeq = JEQ,438 jeq = JEQ,
439 jgt = JGT,439 jgt = JGT,
...@@ -854,7 +854,7 @@ test "opcodes" {...@@ -854,7 +854,7 @@ test "opcodes" {
854 try expect_opcode(0x95, Insn.exit());854 try expect_opcode(0x95, Insn.exit());
855}855}
856856
857pub const Cmd = extern enum(usize) {857pub const Cmd = enum(usize) {
858 /// Create a map and return a file descriptor that refers to the map. The858 /// Create a map and return a file descriptor that refers to the map. The
859 /// close-on-exec file descriptor flag is automatically enabled for the new859 /// close-on-exec file descriptor flag is automatically enabled for the new
860 /// file descriptor.860 /// file descriptor.
...@@ -977,7 +977,7 @@ pub const Cmd = extern enum(usize) {...@@ -977,7 +977,7 @@ pub const Cmd = extern enum(usize) {
977 _,977 _,
978};978};
979979
980pub const MapType = extern enum(u32) {980pub const MapType = enum(u32) {
981 unspec,981 unspec,
982 hash,982 hash,
983 array,983 array,
...@@ -1044,7 +1044,7 @@ pub const MapType = extern enum(u32) {...@@ -1044,7 +1044,7 @@ pub const MapType = extern enum(u32) {
1044 _,1044 _,
1045};1045};
10461046
1047pub const ProgType = extern enum(u32) {1047pub const ProgType = enum(u32) {
1048 unspec,1048 unspec,
10491049
1050 /// context type: __sk_buff1050 /// context type: __sk_buff
...@@ -1139,7 +1139,7 @@ pub const ProgType = extern enum(u32) {...@@ -1139,7 +1139,7 @@ pub const ProgType = extern enum(u32) {
1139 _,1139 _,
1140};1140};
11411141
1142pub const AttachType = extern enum(u32) {1142pub const AttachType = enum(u32) {
1143 cgroup_inet_ingress,1143 cgroup_inet_ingress,
1144 cgroup_inet_egress,1144 cgroup_inet_egress,
1145 cgroup_inet_sock_create,1145 cgroup_inet_sock_create,
lib/std/os/linux/start_pie.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const elf = std.elf;2const elf = std.elf;
3const builtin = @import("builtin");3const builtin = std.builtin;
4const assert = std.debug.assert;4const assert = std.debug.assert;
55
6const R_AMD64_RELATIVE = 8;6const R_AMD64_RELATIVE = 8;
lib/std/os/linux/test.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("../../std.zig");6const std = @import("../../std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const linux = std.os.linux;8const linux = std.os.linux;
9const mem = std.mem;9const mem = std.mem;
10const elf = std.elf;10const elf = std.elf;
lib/std/os/linux/tls.zig+8-8
...@@ -4,12 +4,12 @@...@@ -4,12 +4,12 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const builtin = std.builtin;
8const os = std.os;7const os = std.os;
9const mem = std.mem;8const mem = std.mem;
10const elf = std.elf;9const elf = std.elf;
11const math = std.math;10const math = std.math;
12const assert = std.debug.assert;11const assert = std.debug.assert;
12const native_arch = std.Target.current.cpu.arch;
1313
14// This file implements the two TLS variants [1] used by ELF-based systems.14// This file implements the two TLS variants [1] used by ELF-based systems.
15//15//
...@@ -52,14 +52,14 @@ const TLSVariant = enum {...@@ -52,14 +52,14 @@ const TLSVariant = enum {
52 VariantII,52 VariantII,
53};53};
5454
55const tls_variant = switch (builtin.arch) {55const tls_variant = switch (native_arch) {
56 .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI,56 .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI,
57 .x86_64, .i386, .sparcv9 => TLSVariant.VariantII,57 .x86_64, .i386, .sparcv9 => TLSVariant.VariantII,
58 else => @compileError("undefined tls_variant for this architecture"),58 else => @compileError("undefined tls_variant for this architecture"),
59};59};
6060
61// Controls how many bytes are reserved for the Thread Control Block61// Controls how many bytes are reserved for the Thread Control Block
62const tls_tcb_size = switch (builtin.arch) {62const tls_tcb_size = switch (native_arch) {
63 // ARM EABI mandates enough space for two pointers: the first one points to63 // ARM EABI mandates enough space for two pointers: the first one points to
64 // the DTV while the second one is unspecified but reserved64 // the DTV while the second one is unspecified but reserved
65 .arm, .armeb, .thumb, .aarch64, .aarch64_be => 2 * @sizeOf(usize),65 .arm, .armeb, .thumb, .aarch64, .aarch64_be => 2 * @sizeOf(usize),
...@@ -68,7 +68,7 @@ const tls_tcb_size = switch (builtin.arch) {...@@ -68,7 +68,7 @@ const tls_tcb_size = switch (builtin.arch) {
68};68};
6969
70// Controls if the TP points to the end of the TCB instead of its beginning70// Controls if the TP points to the end of the TCB instead of its beginning
71const tls_tp_points_past_tcb = switch (builtin.arch) {71const tls_tp_points_past_tcb = switch (native_arch) {
72 .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => true,72 .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => true,
73 else => false,73 else => false,
74};74};
...@@ -76,12 +76,12 @@ const tls_tp_points_past_tcb = switch (builtin.arch) {...@@ -76,12 +76,12 @@ const tls_tp_points_past_tcb = switch (builtin.arch) {
76// Some architectures add some offset to the tp and dtv addresses in order to76// Some architectures add some offset to the tp and dtv addresses in order to
77// make the generated code more efficient77// make the generated code more efficient
7878
79const tls_tp_offset = switch (builtin.arch) {79const tls_tp_offset = switch (native_arch) {
80 .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x7000,80 .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x7000,
81 else => 0,81 else => 0,
82};82};
8383
84const tls_dtv_offset = switch (builtin.arch) {84const tls_dtv_offset = switch (native_arch) {
85 .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x8000,85 .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x8000,
86 .riscv32, .riscv64 => 0x800,86 .riscv32, .riscv64 => 0x800,
87 else => 0,87 else => 0,
...@@ -114,7 +114,7 @@ const TLSImage = struct {...@@ -114,7 +114,7 @@ const TLSImage = struct {
114pub var tls_image: TLSImage = undefined;114pub var tls_image: TLSImage = undefined;
115115
116pub fn setThreadPointer(addr: usize) void {116pub fn setThreadPointer(addr: usize) void {
117 switch (builtin.arch) {117 switch (native_arch) {
118 .i386 => {118 .i386 => {
119 var user_desc = std.os.linux.user_desc{119 var user_desc = std.os.linux.user_desc{
120 .entry_number = tls_image.gdt_entry_number,120 .entry_number = tls_image.gdt_entry_number,
...@@ -228,7 +228,7 @@ fn initTLS() void {...@@ -228,7 +228,7 @@ fn initTLS() void {
228 // ARMv6 targets (and earlier) have no support for TLS in hardware228 // ARMv6 targets (and earlier) have no support for TLS in hardware
229 // FIXME: Elide the check for targets >= ARMv7 when the target feature API229 // FIXME: Elide the check for targets >= ARMv7 when the target feature API
230 // becomes less verbose (and more usable).230 // becomes less verbose (and more usable).
231 if (comptime builtin.arch.isARM()) {231 if (comptime native_arch.isARM()) {
232 if (at_hwcap & std.os.linux.HWCAP_TLS == 0) {232 if (at_hwcap & std.os.linux.HWCAP_TLS == 0) {
233 // FIXME: Make __aeabi_read_tp call the kernel helper kuser_get_tls233 // FIXME: Make __aeabi_read_tp call the kernel helper kuser_get_tls
234 // For the time being use a simple abort instead of a @panic call to234 // For the time being use a simple abort instead of a @panic call to
lib/std/os/test.zig+35-34
...@@ -19,14 +19,15 @@ const Thread = std.Thread;...@@ -19,14 +19,15 @@ const Thread = std.Thread;
19const a = std.testing.allocator;19const a = std.testing.allocator;
2020
21const builtin = @import("builtin");21const builtin = @import("builtin");
22const AtomicRmwOp = builtin.AtomicRmwOp;22const AtomicRmwOp = std.builtin.AtomicRmwOp;
23const AtomicOrder = builtin.AtomicOrder;23const AtomicOrder = std.builtin.AtomicOrder;
24const native_os = builtin.target.os.tag;
24const tmpDir = std.testing.tmpDir;25const tmpDir = std.testing.tmpDir;
25const Dir = std.fs.Dir;26const Dir = std.fs.Dir;
26const ArenaAllocator = std.heap.ArenaAllocator;27const ArenaAllocator = std.heap.ArenaAllocator;
2728
28test "chdir smoke test" {29test "chdir smoke test" {
29 if (builtin.os.tag == .wasi) return error.SkipZigTest;30 if (native_os == .wasi) return error.SkipZigTest;
3031
31 // Get current working directory path32 // Get current working directory path
32 var old_cwd_buf: [fs.MAX_PATH_BYTES]u8 = undefined;33 var old_cwd_buf: [fs.MAX_PATH_BYTES]u8 = undefined;
...@@ -52,7 +53,7 @@ test "chdir smoke test" {...@@ -52,7 +53,7 @@ test "chdir smoke test" {
52}53}
5354
54test "open smoke test" {55test "open smoke test" {
55 if (builtin.os.tag == .wasi) return error.SkipZigTest;56 if (native_os == .wasi) return error.SkipZigTest;
5657
57 // TODO verify file attributes using `fstat`58 // TODO verify file attributes using `fstat`
5859
...@@ -70,7 +71,7 @@ test "open smoke test" {...@@ -70,7 +71,7 @@ test "open smoke test" {
7071
71 var file_path: []u8 = undefined;72 var file_path: []u8 = undefined;
72 var fd: os.fd_t = undefined;73 var fd: os.fd_t = undefined;
73 const mode: os.mode_t = if (builtin.os.tag == .windows) 0 else 0o666;74 const mode: os.mode_t = if (native_os == .windows) 0 else 0o666;
7475
75 // Create some file using `open`.76 // Create some file using `open`.
76 file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_file" });77 file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_file" });
...@@ -105,7 +106,7 @@ test "open smoke test" {...@@ -105,7 +106,7 @@ test "open smoke test" {
105}106}
106107
107test "openat smoke test" {108test "openat smoke test" {
108 if (builtin.os.tag == .wasi) return error.SkipZigTest;109 if (native_os == .wasi) return error.SkipZigTest;
109110
110 // TODO verify file attributes using `fstatat`111 // TODO verify file attributes using `fstatat`
111112
...@@ -113,7 +114,7 @@ test "openat smoke test" {...@@ -113,7 +114,7 @@ test "openat smoke test" {
113 defer tmp.cleanup();114 defer tmp.cleanup();
114115
115 var fd: os.fd_t = undefined;116 var fd: os.fd_t = undefined;
116 const mode: os.mode_t = if (builtin.os.tag == .windows) 0 else 0o666;117 const mode: os.mode_t = if (native_os == .windows) 0 else 0o666;
117118
118 // Create some file using `openat`.119 // Create some file using `openat`.
119 fd = try os.openat(tmp.dir.fd, "some_file", os.O_RDWR | os.O_CREAT | os.O_EXCL, mode);120 fd = try os.openat(tmp.dir.fd, "some_file", os.O_RDWR | os.O_CREAT | os.O_EXCL, mode);
...@@ -141,7 +142,7 @@ test "openat smoke test" {...@@ -141,7 +142,7 @@ test "openat smoke test" {
141}142}
142143
143test "symlink with relative paths" {144test "symlink with relative paths" {
144 if (builtin.os.tag == .wasi) return error.SkipZigTest;145 if (native_os == .wasi) return error.SkipZigTest;
145146
146 const cwd = fs.cwd();147 const cwd = fs.cwd();
147 cwd.deleteFile("file.txt") catch {};148 cwd.deleteFile("file.txt") catch {};
...@@ -150,7 +151,7 @@ test "symlink with relative paths" {...@@ -150,7 +151,7 @@ test "symlink with relative paths" {
150 // First, try relative paths in cwd151 // First, try relative paths in cwd
151 try cwd.writeFile("file.txt", "nonsense");152 try cwd.writeFile("file.txt", "nonsense");
152153
153 if (builtin.os.tag == .windows) {154 if (native_os == .windows) {
154 os.windows.CreateSymbolicLink(155 os.windows.CreateSymbolicLink(
155 cwd.fd,156 cwd.fd,
156 &[_]u16{ 's', 'y', 'm', 'l', 'i', 'n', 'k', 'e', 'd' },157 &[_]u16{ 's', 'y', 'm', 'l', 'i', 'n', 'k', 'e', 'd' },
...@@ -178,7 +179,7 @@ test "symlink with relative paths" {...@@ -178,7 +179,7 @@ test "symlink with relative paths" {
178}179}
179180
180test "readlink on Windows" {181test "readlink on Windows" {
181 if (builtin.os.tag != .windows) return error.SkipZigTest;182 if (native_os != .windows) return error.SkipZigTest;
182183
183 try testReadlink("C:\\ProgramData", "C:\\Users\\All Users");184 try testReadlink("C:\\ProgramData", "C:\\Users\\All Users");
184 try testReadlink("C:\\Users\\Default", "C:\\Users\\Default User");185 try testReadlink("C:\\Users\\Default", "C:\\Users\\Default User");
...@@ -192,7 +193,7 @@ fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void {...@@ -192,7 +193,7 @@ fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void {
192}193}
193194
194test "link with relative paths" {195test "link with relative paths" {
195 if (builtin.os.tag != .linux) return error.SkipZigTest;196 if (native_os != .linux) return error.SkipZigTest;
196 var cwd = fs.cwd();197 var cwd = fs.cwd();
197198
198 cwd.deleteFile("example.txt") catch {};199 cwd.deleteFile("example.txt") catch {};
...@@ -226,7 +227,7 @@ test "link with relative paths" {...@@ -226,7 +227,7 @@ test "link with relative paths" {
226}227}
227228
228test "linkat with different directories" {229test "linkat with different directories" {
229 if (builtin.os.tag != .linux) return error.SkipZigTest;230 if (native_os != .linux) return error.SkipZigTest;
230 var cwd = fs.cwd();231 var cwd = fs.cwd();
231 var tmp = tmpDir(.{});232 var tmp = tmpDir(.{});
232233
...@@ -262,7 +263,7 @@ test "linkat with different directories" {...@@ -262,7 +263,7 @@ test "linkat with different directories" {
262263
263test "fstatat" {264test "fstatat" {
264 // enable when `fstat` and `fstatat` are implemented on Windows265 // enable when `fstat` and `fstatat` are implemented on Windows
265 if (builtin.os.tag == .windows) return error.SkipZigTest;266 if (native_os == .windows) return error.SkipZigTest;
266267
267 var tmp = tmpDir(.{});268 var tmp = tmpDir(.{});
268 defer tmp.cleanup();269 defer tmp.cleanup();
...@@ -277,7 +278,7 @@ test "fstatat" {...@@ -277,7 +278,7 @@ test "fstatat" {
277 defer file.close();278 defer file.close();
278279
279 // now repeat but using `fstatat` instead280 // now repeat but using `fstatat` instead
280 const flags = if (builtin.os.tag == .wasi) 0x0 else os.AT_SYMLINK_NOFOLLOW;281 const flags = if (native_os == .wasi) 0x0 else os.AT_SYMLINK_NOFOLLOW;
281 const statat = try os.fstatat(tmp.dir.fd, "file.txt", flags);282 const statat = try os.fstatat(tmp.dir.fd, "file.txt", flags);
282 try expectEqual(stat, statat);283 try expectEqual(stat, statat);
283}284}
...@@ -290,7 +291,7 @@ test "readlinkat" {...@@ -290,7 +291,7 @@ test "readlinkat" {
290 try tmp.dir.writeFile("file.txt", "nonsense");291 try tmp.dir.writeFile("file.txt", "nonsense");
291292
292 // create a symbolic link293 // create a symbolic link
293 if (builtin.os.tag == .windows) {294 if (native_os == .windows) {
294 os.windows.CreateSymbolicLink(295 os.windows.CreateSymbolicLink(
295 tmp.dir.fd,296 tmp.dir.fd,
296 &[_]u16{ 'l', 'i', 'n', 'k' },297 &[_]u16{ 'l', 'i', 'n', 'k' },
...@@ -324,7 +325,7 @@ test "std.Thread.getCurrentId" {...@@ -324,7 +325,7 @@ test "std.Thread.getCurrentId" {
324 thread.wait();325 thread.wait();
325 if (Thread.use_pthreads) {326 if (Thread.use_pthreads) {
326 try expect(thread_current_id == thread_id);327 try expect(thread_current_id == thread_id);
327 } else if (builtin.os.tag == .windows) {328 } else if (native_os == .windows) {
328 try expect(Thread.getCurrentId() != thread_current_id);329 try expect(Thread.getCurrentId() != thread_current_id);
329 } else {330 } else {
330 // If the thread completes very quickly, then thread_id can be 0. See the331 // If the thread completes very quickly, then thread_id can be 0. See the
...@@ -361,7 +362,7 @@ fn start2(ctx: *i32) u8 {...@@ -361,7 +362,7 @@ fn start2(ctx: *i32) u8 {
361}362}
362363
363test "cpu count" {364test "cpu count" {
364 if (builtin.os.tag == .wasi) return error.SkipZigTest;365 if (native_os == .wasi) return error.SkipZigTest;
365366
366 const cpu_count = try Thread.cpuCount();367 const cpu_count = try Thread.cpuCount();
367 try expect(cpu_count >= 1);368 try expect(cpu_count >= 1);
...@@ -394,7 +395,7 @@ test "getrandom" {...@@ -394,7 +395,7 @@ test "getrandom" {
394}395}
395396
396test "getcwd" {397test "getcwd" {
397 if (builtin.os.tag == .wasi) return error.SkipZigTest;398 if (native_os == .wasi) return error.SkipZigTest;
398399
399 // at least call it so it gets compiled400 // at least call it so it gets compiled
400 var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;401 var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
...@@ -402,7 +403,7 @@ test "getcwd" {...@@ -402,7 +403,7 @@ test "getcwd" {
402}403}
403404
404test "sigaltstack" {405test "sigaltstack" {
405 if (builtin.os.tag == .windows or builtin.os.tag == .wasi) return error.SkipZigTest;406 if (native_os == .windows or native_os == .wasi) return error.SkipZigTest;
406407
407 var st: os.stack_t = undefined;408 var st: os.stack_t = undefined;
408 try os.sigaltstack(null, &st);409 try os.sigaltstack(null, &st);
...@@ -455,7 +456,7 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {...@@ -455,7 +456,7 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {
455}456}
456457
457test "dl_iterate_phdr" {458test "dl_iterate_phdr" {
458 if (builtin.os.tag == .windows or builtin.os.tag == .wasi or builtin.os.tag == .macos)459 if (native_os == .windows or native_os == .wasi or native_os == .macos)
459 return error.SkipZigTest;460 return error.SkipZigTest;
460461
461 var counter: usize = 0;462 var counter: usize = 0;
...@@ -464,7 +465,7 @@ test "dl_iterate_phdr" {...@@ -464,7 +465,7 @@ test "dl_iterate_phdr" {
464}465}
465466
466test "gethostname" {467test "gethostname" {
467 if (builtin.os.tag == .windows or builtin.os.tag == .wasi)468 if (native_os == .windows or native_os == .wasi)
468 return error.SkipZigTest;469 return error.SkipZigTest;
469470
470 var buf: [os.HOST_NAME_MAX]u8 = undefined;471 var buf: [os.HOST_NAME_MAX]u8 = undefined;
...@@ -473,7 +474,7 @@ test "gethostname" {...@@ -473,7 +474,7 @@ test "gethostname" {
473}474}
474475
475test "pipe" {476test "pipe" {
476 if (builtin.os.tag == .windows or builtin.os.tag == .wasi)477 if (native_os == .windows or native_os == .wasi)
477 return error.SkipZigTest;478 return error.SkipZigTest;
478479
479 var fds = try os.pipe();480 var fds = try os.pipe();
...@@ -492,7 +493,7 @@ test "argsAlloc" {...@@ -492,7 +493,7 @@ test "argsAlloc" {
492493
493test "memfd_create" {494test "memfd_create" {
494 // memfd_create is linux specific.495 // memfd_create is linux specific.
495 if (builtin.os.tag != .linux) return error.SkipZigTest;496 if (native_os != .linux) return error.SkipZigTest;
496 const fd = std.os.memfd_create("test", 0) catch |err| switch (err) {497 const fd = std.os.memfd_create("test", 0) catch |err| switch (err) {
497 // Related: https://github.com/ziglang/zig/issues/4019498 // Related: https://github.com/ziglang/zig/issues/4019
498 error.SystemOutdated => return error.SkipZigTest,499 error.SystemOutdated => return error.SkipZigTest,
...@@ -509,7 +510,7 @@ test "memfd_create" {...@@ -509,7 +510,7 @@ test "memfd_create" {
509}510}
510511
511test "mmap" {512test "mmap" {
512 if (builtin.os.tag == .windows or builtin.os.tag == .wasi)513 if (native_os == .windows or native_os == .wasi)
513 return error.SkipZigTest;514 return error.SkipZigTest;
514515
515 var tmp = tmpDir(.{});516 var tmp = tmpDir(.{});
...@@ -606,7 +607,7 @@ test "mmap" {...@@ -606,7 +607,7 @@ test "mmap" {
606}607}
607608
608test "getenv" {609test "getenv" {
609 if (builtin.os.tag == .windows) {610 if (native_os == .windows) {
610 try expect(os.getenvW(&[_:0]u16{ 'B', 'O', 'G', 'U', 'S', 0x11, 0x22, 0x33, 0x44, 0x55 }) == null);611 try expect(os.getenvW(&[_:0]u16{ 'B', 'O', 'G', 'U', 'S', 0x11, 0x22, 0x33, 0x44, 0x55 }) == null);
611 } else {612 } else {
612 try expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);613 try expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);
...@@ -614,7 +615,7 @@ test "getenv" {...@@ -614,7 +615,7 @@ test "getenv" {
614}615}
615616
616test "fcntl" {617test "fcntl" {
617 if (builtin.os.tag == .windows or builtin.os.tag == .wasi)618 if (native_os == .windows or native_os == .wasi)
618 return error.SkipZigTest;619 return error.SkipZigTest;
619620
620 var tmp = tmpDir(.{});621 var tmp = tmpDir(.{});
...@@ -646,13 +647,13 @@ test "fcntl" {...@@ -646,13 +647,13 @@ test "fcntl" {
646}647}
647648
648test "signalfd" {649test "signalfd" {
649 if (builtin.os.tag != .linux)650 if (native_os != .linux)
650 return error.SkipZigTest;651 return error.SkipZigTest;
651 _ = std.os.signalfd;652 _ = std.os.signalfd;
652}653}
653654
654test "sync" {655test "sync" {
655 if (builtin.os.tag != .linux)656 if (native_os != .linux)
656 return error.SkipZigTest;657 return error.SkipZigTest;
657658
658 var tmp = tmpDir(.{});659 var tmp = tmpDir(.{});
...@@ -670,7 +671,7 @@ test "sync" {...@@ -670,7 +671,7 @@ test "sync" {
670}671}
671672
672test "fsync" {673test "fsync" {
673 if (builtin.os.tag != .linux and builtin.os.tag != .windows)674 if (native_os != .linux and native_os != .windows)
674 return error.SkipZigTest;675 return error.SkipZigTest;
675676
676 var tmp = tmpDir(.{});677 var tmp = tmpDir(.{});
...@@ -700,13 +701,13 @@ test "getrlimit and setrlimit" {...@@ -700,13 +701,13 @@ test "getrlimit and setrlimit" {
700}701}
701702
702test "shutdown socket" {703test "shutdown socket" {
703 if (builtin.os.tag == .wasi)704 if (native_os == .wasi)
704 return error.SkipZigTest;705 return error.SkipZigTest;
705 if (builtin.os.tag == .windows) {706 if (native_os == .windows) {
706 _ = try std.os.windows.WSAStartup(2, 2);707 _ = try std.os.windows.WSAStartup(2, 2);
707 }708 }
708 defer {709 defer {
709 if (builtin.os.tag == .windows) {710 if (native_os == .windows) {
710 std.os.windows.WSACleanup() catch unreachable;711 std.os.windows.WSACleanup() catch unreachable;
711 }712 }
712 }713 }
...@@ -721,11 +722,11 @@ test "shutdown socket" {...@@ -721,11 +722,11 @@ test "shutdown socket" {
721var signal_test_failed = true;722var signal_test_failed = true;
722723
723test "sigaction" {724test "sigaction" {
724 if (builtin.os.tag == .wasi or builtin.os.tag == .windows)725 if (native_os == .wasi or native_os == .windows)
725 return error.SkipZigTest;726 return error.SkipZigTest;
726727
727 // https://github.com/ziglang/zig/issues/7427728 // https://github.com/ziglang/zig/issues/7427
728 if (builtin.os.tag == .linux and builtin.arch == .i386)729 if (native_os == .linux and builtin.target.cpu.arch == .i386)
729 return error.SkipZigTest;730 return error.SkipZigTest;
730731
731 const S = struct {732 const S = struct {
lib/std/os/uefi/protocols/device_path_protocol.zig+7-7
...@@ -90,7 +90,7 @@ pub const DevicePath = union(DevicePathType) {...@@ -90,7 +90,7 @@ pub const DevicePath = union(DevicePathType) {
90 End: EndDevicePath,90 End: EndDevicePath,
91};91};
9292
93pub const DevicePathType = extern enum(u8) {93pub const DevicePathType = enum(u8) {
94 Hardware = 0x01,94 Hardware = 0x01,
95 Acpi = 0x02,95 Acpi = 0x02,
96 Messaging = 0x03,96 Messaging = 0x03,
...@@ -108,7 +108,7 @@ pub const HardwareDevicePath = union(Subtype) {...@@ -108,7 +108,7 @@ pub const HardwareDevicePath = union(Subtype) {
108 Controller: *const ControllerDevicePath,108 Controller: *const ControllerDevicePath,
109 Bmc: *const BmcDevicePath,109 Bmc: *const BmcDevicePath,
110110
111 pub const Subtype = extern enum(u8) {111 pub const Subtype = enum(u8) {
112 Pci = 1,112 Pci = 1,
113 PcCard = 2,113 PcCard = 2,
114 MemoryMapped = 3,114 MemoryMapped = 3,
...@@ -167,7 +167,7 @@ pub const AcpiDevicePath = union(Subtype) {...@@ -167,7 +167,7 @@ pub const AcpiDevicePath = union(Subtype) {
167 Adr: void, // TODO167 Adr: void, // TODO
168 Nvdimm: void, // TODO168 Nvdimm: void, // TODO
169169
170 pub const Subtype = extern enum(u8) {170 pub const Subtype = enum(u8) {
171 Acpi = 1,171 Acpi = 1,
172 ExpandedAcpi = 2,172 ExpandedAcpi = 2,
173 Adr = 3,173 Adr = 3,
...@@ -196,7 +196,7 @@ pub const MessagingDevicePath = union(Subtype) {...@@ -196,7 +196,7 @@ pub const MessagingDevicePath = union(Subtype) {
196 Uart: void, // TODO196 Uart: void, // TODO
197 Vendor: void, // TODO197 Vendor: void, // TODO
198198
199 pub const Subtype = extern enum(u8) {199 pub const Subtype = enum(u8) {
200 Atapi = 1,200 Atapi = 1,
201 Scsi = 2,201 Scsi = 2,
202 FibreChannel = 3,202 FibreChannel = 3,
...@@ -230,7 +230,7 @@ pub const MediaDevicePath = union(Subtype) {...@@ -230,7 +230,7 @@ pub const MediaDevicePath = union(Subtype) {
230 RelativeOffsetRange: *const RelativeOffsetRangeDevicePath,230 RelativeOffsetRange: *const RelativeOffsetRangeDevicePath,
231 RamDisk: *const RamDiskDevicePath,231 RamDisk: *const RamDiskDevicePath,
232232
233 pub const Subtype = extern enum(u8) {233 pub const Subtype = enum(u8) {
234 HardDrive = 1,234 HardDrive = 1,
235 Cdrom = 2,235 Cdrom = 2,
236 Vendor = 3,236 Vendor = 3,
...@@ -316,7 +316,7 @@ pub const MediaDevicePath = union(Subtype) {...@@ -316,7 +316,7 @@ pub const MediaDevicePath = union(Subtype) {
316pub const BiosBootSpecificationDevicePath = union(Subtype) {316pub const BiosBootSpecificationDevicePath = union(Subtype) {
317 BBS101: *const BBS101DevicePath,317 BBS101: *const BBS101DevicePath,
318318
319 pub const Subtype = extern enum(u8) {319 pub const Subtype = enum(u8) {
320 BBS101 = 1,320 BBS101 = 1,
321 _,321 _,
322 };322 };
...@@ -338,7 +338,7 @@ pub const EndDevicePath = union(Subtype) {...@@ -338,7 +338,7 @@ pub const EndDevicePath = union(Subtype) {
338 EndEntire: *const EndEntireDevicePath,338 EndEntire: *const EndEntireDevicePath,
339 EndThisInstance: *const EndThisInstanceDevicePath,339 EndThisInstance: *const EndThisInstanceDevicePath,
340340
341 pub const Subtype = extern enum(u8) {341 pub const Subtype = enum(u8) {
342 EndEntire = 0xff,342 EndEntire = 0xff,
343 EndThisInstance = 0x01,343 EndThisInstance = 0x01,
344 _,344 _,
lib/std/os/uefi/protocols/graphics_output_protocol.zig+2-2
...@@ -57,7 +57,7 @@ pub const GraphicsOutputModeInformation = extern struct {...@@ -57,7 +57,7 @@ pub const GraphicsOutputModeInformation = extern struct {
57 pixels_per_scan_line: u32 = undefined,57 pixels_per_scan_line: u32 = undefined,
58};58};
5959
60pub const GraphicsPixelFormat = extern enum(u32) {60pub const GraphicsPixelFormat = enum(u32) {
61 PixelRedGreenBlueReserved8BitPerColor,61 PixelRedGreenBlueReserved8BitPerColor,
62 PixelBlueGreenRedReserved8BitPerColor,62 PixelBlueGreenRedReserved8BitPerColor,
63 PixelBitMask,63 PixelBitMask,
...@@ -79,7 +79,7 @@ pub const GraphicsOutputBltPixel = extern struct {...@@ -79,7 +79,7 @@ pub const GraphicsOutputBltPixel = extern struct {
79 reserved: u8 = undefined,79 reserved: u8 = undefined,
80};80};
8181
82pub const GraphicsOutputBltOperation = extern enum(u32) {82pub const GraphicsOutputBltOperation = enum(u32) {
83 BltVideoFill,83 BltVideoFill,
84 BltVideoToBltBuffer,84 BltVideoToBltBuffer,
85 BltBufferToVideo,85 BltBufferToVideo,
lib/std/os/uefi/protocols/hii_popup_protocol.zig+3-3
...@@ -28,20 +28,20 @@ pub const HIIPopupProtocol = extern struct {...@@ -28,20 +28,20 @@ pub const HIIPopupProtocol = extern struct {
28 };28 };
29};29};
3030
31pub const HIIPopupStyle = extern enum(u32) {31pub const HIIPopupStyle = enum(u32) {
32 Info,32 Info,
33 Warning,33 Warning,
34 Error,34 Error,
35};35};
3636
37pub const HIIPopupType = extern enum(u32) {37pub const HIIPopupType = enum(u32) {
38 Ok,38 Ok,
39 Cancel,39 Cancel,
40 YesNo,40 YesNo,
41 YesNoCancel,41 YesNoCancel,
42};42};
4343
44pub const HIIPopupSelection = extern enum(u32) {44pub const HIIPopupSelection = enum(u32) {
45 Ok,45 Ok,
46 Cancel,46 Cancel,
47 Yes,47 Yes,
lib/std/os/uefi/protocols/ip6_config_protocol.zig+1-1
...@@ -40,7 +40,7 @@ pub const Ip6ConfigProtocol = extern struct {...@@ -40,7 +40,7 @@ pub const Ip6ConfigProtocol = extern struct {
40 };40 };
41};41};
4242
43pub const Ip6ConfigDataType = extern enum(u32) {43pub const Ip6ConfigDataType = enum(u32) {
44 InterfaceInfo,44 InterfaceInfo,
45 AltInterfaceId,45 AltInterfaceId,
46 Policy,46 Policy,
lib/std/os/uefi/protocols/ip6_protocol.zig+1-1
...@@ -123,7 +123,7 @@ pub const Ip6RouteTable = extern struct {...@@ -123,7 +123,7 @@ pub const Ip6RouteTable = extern struct {
123 prefix_length: u8,123 prefix_length: u8,
124};124};
125125
126pub const Ip6NeighborState = extern enum(u32) {126pub const Ip6NeighborState = enum(u32) {
127 Incomplete,127 Incomplete,
128 Reachable,128 Reachable,
129 Stale,129 Stale,
lib/std/os/uefi/protocols/simple_network_protocol.zig+1-1
...@@ -134,7 +134,7 @@ pub const SimpleNetworkReceiveFilter = packed struct {...@@ -134,7 +134,7 @@ pub const SimpleNetworkReceiveFilter = packed struct {
134 _pad: u27 = undefined,134 _pad: u27 = undefined,
135};135};
136136
137pub const SimpleNetworkState = extern enum(u32) {137pub const SimpleNetworkState = enum(u32) {
138 Stopped,138 Stopped,
139 Started,139 Started,
140 Initialized,140 Initialized,
lib/std/os/uefi/status.zig+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5// and substantial portions of the software.5// and substantial portions of the software.
6const high_bit = 1 << @typeInfo(usize).Int.bits - 1;6const high_bit = 1 << @typeInfo(usize).Int.bits - 1;
77
8pub const Status = extern enum(usize) {8pub const Status = enum(usize) {
9 /// The operation completed successfully.9 /// The operation completed successfully.
10 Success = 0,10 Success = 0,
1111
lib/std/os/uefi/tables/boot_services.zig+4-4
...@@ -156,13 +156,13 @@ pub const BootServices = extern struct {...@@ -156,13 +156,13 @@ pub const BootServices = extern struct {
156 pub const tpl_high_level: usize = 31;156 pub const tpl_high_level: usize = 31;
157};157};
158158
159pub const TimerDelay = extern enum(u32) {159pub const TimerDelay = enum(u32) {
160 TimerCancel,160 TimerCancel,
161 TimerPeriodic,161 TimerPeriodic,
162 TimerRelative,162 TimerRelative,
163};163};
164164
165pub const MemoryType = extern enum(u32) {165pub const MemoryType = enum(u32) {
166 ReservedMemoryType,166 ReservedMemoryType,
167 LoaderCode,167 LoaderCode,
168 LoaderData,168 LoaderData,
...@@ -206,7 +206,7 @@ pub const MemoryDescriptor = extern struct {...@@ -206,7 +206,7 @@ pub const MemoryDescriptor = extern struct {
206 },206 },
207};207};
208208
209pub const LocateSearchType = extern enum(u32) {209pub const LocateSearchType = enum(u32) {
210 AllHandles,210 AllHandles,
211 ByRegisterNotify,211 ByRegisterNotify,
212 ByProtocol,212 ByProtocol,
...@@ -229,7 +229,7 @@ pub const ProtocolInformationEntry = extern struct {...@@ -229,7 +229,7 @@ pub const ProtocolInformationEntry = extern struct {
229 open_count: u32,229 open_count: u32,
230};230};
231231
232pub const AllocateType = extern enum(u32) {232pub const AllocateType = enum(u32) {
233 AllocateAnyPages,233 AllocateAnyPages,
234 AllocateMaxAddress,234 AllocateMaxAddress,
235 AllocateAddress,235 AllocateAddress,
lib/std/os/uefi/tables/runtime_services.zig+1-1
...@@ -51,7 +51,7 @@ pub const RuntimeServices = extern struct {...@@ -51,7 +51,7 @@ pub const RuntimeServices = extern struct {
51 pub const signature: u64 = 0x56524553544e5552;51 pub const signature: u64 = 0x56524553544e5552;
52};52};
5353
54pub const ResetType = extern enum(u32) {54pub const ResetType = enum(u32) {
55 ResetCold,55 ResetCold,
56 ResetWarm,56 ResetWarm,
57 ResetShutdown,57 ResetShutdown,
lib/std/os/windows.zig+3-3
...@@ -1022,7 +1022,7 @@ pub fn QueryObjectName(...@@ -1022,7 +1022,7 @@ pub fn QueryObjectName(
1022 }1022 }
1023}1023}
1024test "QueryObjectName" {1024test "QueryObjectName" {
1025 if (comptime builtin.os.tag != .windows)1025 if (comptime builtin.target.os.tag != .windows)
1026 return;1026 return;
10271027
1028 //any file will do; canonicalization works on NTFS junctions and symlinks, hardlinks remain separate paths.1028 //any file will do; canonicalization works on NTFS junctions and symlinks, hardlinks remain separate paths.
...@@ -1177,7 +1177,7 @@ pub fn GetFinalPathNameByHandle(...@@ -1177,7 +1177,7 @@ pub fn GetFinalPathNameByHandle(
1177}1177}
11781178
1179test "GetFinalPathNameByHandle" {1179test "GetFinalPathNameByHandle" {
1180 if (comptime builtin.os.tag != .windows)1180 if (comptime builtin.target.os.tag != .windows)
1181 return;1181 return;
11821182
1183 //any file will do1183 //any file will do
...@@ -1617,7 +1617,7 @@ pub fn SetFileTime(...@@ -1617,7 +1617,7 @@ pub fn SetFileTime(
1617}1617}
16181618
1619pub fn teb() *TEB {1619pub fn teb() *TEB {
1620 return switch (builtin.arch) {1620 return switch (builtin.target.cpu.arch) {
1621 .i386 => asm volatile (1621 .i386 => asm volatile (
1622 \\ movl %%fs:0x18, %[ptr]1622 \\ movl %%fs:0x18, %[ptr]
1623 : [ptr] "=r" (-> *TEB)1623 : [ptr] "=r" (-> *TEB)
lib/std/os/windows/bits.zig+6-6
...@@ -5,10 +5,10 @@...@@ -5,10 +5,10 @@
5// and substantial portions of the software.5// and substantial portions of the software.
6// Platform-dependent types and values that are used along with OS-specific APIs.6// Platform-dependent types and values that are used along with OS-specific APIs.
77
8const builtin = @import("builtin");
9const std = @import("../../std.zig");8const std = @import("../../std.zig");
10const assert = std.debug.assert;9const assert = std.debug.assert;
11const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
11const arch = std.Target.current.cpu.arch;
1212
13pub usingnamespace @import("win32error.zig");13pub usingnamespace @import("win32error.zig");
14pub usingnamespace @import("ntstatus.zig");14pub usingnamespace @import("ntstatus.zig");
...@@ -24,7 +24,7 @@ pub const STD_OUTPUT_HANDLE = maxInt(DWORD) - 11 + 1;...@@ -24,7 +24,7 @@ pub const STD_OUTPUT_HANDLE = maxInt(DWORD) - 11 + 1;
24/// The standard error device. Initially, this is the active console screen buffer, CONOUT$.24/// The standard error device. Initially, this is the active console screen buffer, CONOUT$.
25pub const STD_ERROR_HANDLE = maxInt(DWORD) - 12 + 1;25pub const STD_ERROR_HANDLE = maxInt(DWORD) - 12 + 1;
2626
27pub const WINAPI: builtin.CallingConvention = if (builtin.arch == .i386)27pub const WINAPI: std.builtin.CallingConvention = if (arch == .i386)
28 .Stdcall28 .Stdcall
29else29else
30 .C;30 .C;
...@@ -281,7 +281,7 @@ pub const IO_STATUS_BLOCK = extern struct {...@@ -281,7 +281,7 @@ pub const IO_STATUS_BLOCK = extern struct {
281 Information: ULONG_PTR,281 Information: ULONG_PTR,
282};282};
283283
284pub const FILE_INFORMATION_CLASS = extern enum {284pub const FILE_INFORMATION_CLASS = enum(c_int) {
285 FileDirectoryInformation = 1,285 FileDirectoryInformation = 1,
286 FileFullDirectoryInformation,286 FileFullDirectoryInformation,
287 FileBothDirectoryInformation,287 FileBothDirectoryInformation,
...@@ -901,7 +901,7 @@ pub const COINIT_APARTMENTTHREADED = COINIT.COINIT_APARTMENTTHREADED;...@@ -901,7 +901,7 @@ pub const COINIT_APARTMENTTHREADED = COINIT.COINIT_APARTMENTTHREADED;
901pub const COINIT_MULTITHREADED = COINIT.COINIT_MULTITHREADED;901pub const COINIT_MULTITHREADED = COINIT.COINIT_MULTITHREADED;
902pub const COINIT_DISABLE_OLE1DDE = COINIT.COINIT_DISABLE_OLE1DDE;902pub const COINIT_DISABLE_OLE1DDE = COINIT.COINIT_DISABLE_OLE1DDE;
903pub const COINIT_SPEED_OVER_MEMORY = COINIT.COINIT_SPEED_OVER_MEMORY;903pub const COINIT_SPEED_OVER_MEMORY = COINIT.COINIT_SPEED_OVER_MEMORY;
904pub const COINIT = extern enum {904pub const COINIT = enum(c_int) {
905 COINIT_APARTMENTTHREADED = 2,905 COINIT_APARTMENTTHREADED = 2,
906 COINIT_MULTITHREADED = 0,906 COINIT_MULTITHREADED = 0,
907 COINIT_DISABLE_OLE1DDE = 4,907 COINIT_DISABLE_OLE1DDE = 4,
...@@ -937,7 +937,7 @@ pub const EXCEPTION_RECORD = extern struct {...@@ -937,7 +937,7 @@ pub const EXCEPTION_RECORD = extern struct {
937 ExceptionInformation: [15]usize,937 ExceptionInformation: [15]usize,
938};938};
939939
940pub usingnamespace switch (builtin.arch) {940pub usingnamespace switch (arch) {
941 .i386 => struct {941 .i386 => struct {
942 pub const FLOATING_SAVE_AREA = extern struct {942 pub const FLOATING_SAVE_AREA = extern struct {
943 ControlWord: DWORD,943 ControlWord: DWORD,
...@@ -1619,7 +1619,7 @@ pub const MOUNTMGR_MOUNT_POINTS = extern struct {...@@ -1619,7 +1619,7 @@ pub const MOUNTMGR_MOUNT_POINTS = extern struct {
1619};1619};
1620pub const IOCTL_MOUNTMGR_QUERY_POINTS: ULONG = 0x6d0008;1620pub const IOCTL_MOUNTMGR_QUERY_POINTS: ULONG = 0x6d0008;
16211621
1622pub const OBJECT_INFORMATION_CLASS = extern enum {1622pub const OBJECT_INFORMATION_CLASS = enum(c_int) {
1623 ObjectBasicInformation = 0,1623 ObjectBasicInformation = 0,
1624 ObjectNameInformation = 1,1624 ObjectNameInformation = 1,
1625 ObjectTypeInformation = 2,1625 ObjectTypeInformation = 2,
lib/std/os/windows/ntstatus.zig+11-1803
...@@ -3,5603 +3,3811 @@...@@ -3,5603 +3,3811 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6// NTSTATUS codes from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55?
7pub const NTSTATUS = extern enum(u32) {
8 /// The operation completed successfully.
9 SUCCESS = 0x00000000,
106
11 /// The caller specified WaitAny for WaitType and one of the dispatcher objects in the Object array has been set to the signaled state.7/// NTSTATUS codes from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55?
12 WAIT_0 = 0x00000000,8pub const NTSTATUS = enum(u32) {
9 /// The caller specified WaitAny for WaitType and one of the dispatcher
10 /// objects in the Object array has been set to the signaled state.
11 pub const WAIT_0: NTSTATUS = .SUCCESS;
12 /// The caller attempted to wait for a mutex that has been abandoned.
13 pub const ABANDONED_WAIT_0: NTSTATUS = .ABANDONED;
14 /// The maximum number of boot-time filters has been reached.
15 pub const FWP_TOO_MANY_BOOTTIME_FILTERS: NTSTATUS = .FWP_TOO_MANY_CALLOUTS;
1316
17 /// The operation completed successfully.
18 SUCCESS = 0x00000000,
14 /// The caller specified WaitAny for WaitType and one of the dispatcher objects in the Object array has been set to the signaled state.19 /// The caller specified WaitAny for WaitType and one of the dispatcher objects in the Object array has been set to the signaled state.
15 WAIT_1 = 0x00000001,20 WAIT_1 = 0x00000001,
16
17 /// The caller specified WaitAny for WaitType and one of the dispatcher objects in the Object array has been set to the signaled state.21 /// The caller specified WaitAny for WaitType and one of the dispatcher objects in the Object array has been set to the signaled state.
18 WAIT_2 = 0x00000002,22 WAIT_2 = 0x00000002,
19
20 /// The caller specified WaitAny for WaitType and one of the dispatcher objects in the Object array has been set to the signaled state.23 /// The caller specified WaitAny for WaitType and one of the dispatcher objects in the Object array has been set to the signaled state.
21 WAIT_3 = 0x00000003,24 WAIT_3 = 0x00000003,
22
23 /// The caller specified WaitAny for WaitType and one of the dispatcher objects in the Object array has been set to the signaled state.25 /// The caller specified WaitAny for WaitType and one of the dispatcher objects in the Object array has been set to the signaled state.
24 WAIT_63 = 0x0000003F,26 WAIT_63 = 0x0000003F,
25
26 /// The caller attempted to wait for a mutex that has been abandoned.27 /// The caller attempted to wait for a mutex that has been abandoned.
27 ABANDONED = 0x00000080,28 ABANDONED = 0x00000080,
28
29 /// The caller attempted to wait for a mutex that has been abandoned.
30 ABANDONED_WAIT_0 = 0x00000080,
31
32 /// The caller attempted to wait for a mutex that has been abandoned.29 /// The caller attempted to wait for a mutex that has been abandoned.
33 ABANDONED_WAIT_63 = 0x000000BF,30 ABANDONED_WAIT_63 = 0x000000BF,
34
35 /// A user-mode APC was delivered before the given Interval expired.31 /// A user-mode APC was delivered before the given Interval expired.
36 USER_APC = 0x000000C0,32 USER_APC = 0x000000C0,
37
38 /// The delay completed because the thread was alerted.33 /// The delay completed because the thread was alerted.
39 ALERTED = 0x00000101,34 ALERTED = 0x00000101,
40
41 /// The given Timeout interval expired.35 /// The given Timeout interval expired.
42 TIMEOUT = 0x00000102,36 TIMEOUT = 0x00000102,
43
44 /// The operation that was requested is pending completion.37 /// The operation that was requested is pending completion.
45 PENDING = 0x00000103,38 PENDING = 0x00000103,
46
47 /// A reparse should be performed by the Object Manager because the name of the file resulted in a symbolic link.39 /// A reparse should be performed by the Object Manager because the name of the file resulted in a symbolic link.
48 REPARSE = 0x00000104,40 REPARSE = 0x00000104,
49
50 /// Returned by enumeration APIs to indicate more information is available to successive calls.41 /// Returned by enumeration APIs to indicate more information is available to successive calls.
51 MORE_ENTRIES = 0x00000105,42 MORE_ENTRIES = 0x00000105,
52
53 /// Indicates not all privileges or groups that are referenced are assigned to the caller.43 /// Indicates not all privileges or groups that are referenced are assigned to the caller.
54 /// This allows, for example, all privileges to be disabled without having to know exactly which privileges are assigned.44 /// This allows, for example, all privileges to be disabled without having to know exactly which privileges are assigned.
55 NOT_ALL_ASSIGNED = 0x00000106,45 NOT_ALL_ASSIGNED = 0x00000106,
56
57 /// Some of the information to be translated has not been translated.46 /// Some of the information to be translated has not been translated.
58 SOME_NOT_MAPPED = 0x00000107,47 SOME_NOT_MAPPED = 0x00000107,
59
60 /// An open/create operation completed while an opportunistic lock (oplock) break is underway.48 /// An open/create operation completed while an opportunistic lock (oplock) break is underway.
61 OPLOCK_BREAK_IN_PROGRESS = 0x00000108,49 OPLOCK_BREAK_IN_PROGRESS = 0x00000108,
62
63 /// A new volume has been mounted by a file system.50 /// A new volume has been mounted by a file system.
64 VOLUME_MOUNTED = 0x00000109,51 VOLUME_MOUNTED = 0x00000109,
65
66 /// This success level status indicates that the transaction state already exists for the registry subtree but that a transaction commit was previously aborted. The commit has now been completed.52 /// This success level status indicates that the transaction state already exists for the registry subtree but that a transaction commit was previously aborted. The commit has now been completed.
67 RXACT_COMMITTED = 0x0000010A,53 RXACT_COMMITTED = 0x0000010A,
68
69 /// Indicates that a notify change request has been completed due to closing the handle that made the notify change request.54 /// Indicates that a notify change request has been completed due to closing the handle that made the notify change request.
70 NOTIFY_CLEANUP = 0x0000010B,55 NOTIFY_CLEANUP = 0x0000010B,
71
72 /// Indicates that a notify change request is being completed and that the information is not being returned in the caller's buffer.56 /// Indicates that a notify change request is being completed and that the information is not being returned in the caller's buffer.
73 /// The caller now needs to enumerate the files to find the changes.57 /// The caller now needs to enumerate the files to find the changes.
74 NOTIFY_ENUM_DIR = 0x0000010C,58 NOTIFY_ENUM_DIR = 0x0000010C,
75
76 /// {No Quotas} No system quota limits are specifically set for this account.59 /// {No Quotas} No system quota limits are specifically set for this account.
77 NO_QUOTAS_FOR_ACCOUNT = 0x0000010D,60 NO_QUOTAS_FOR_ACCOUNT = 0x0000010D,
78
79 /// {Connect Failure on Primary Transport} An attempt was made to connect to the remote server %hs on the primary transport, but the connection failed.61 /// {Connect Failure on Primary Transport} An attempt was made to connect to the remote server %hs on the primary transport, but the connection failed.
80 /// The computer WAS able to connect on a secondary transport.62 /// The computer WAS able to connect on a secondary transport.
81 PRIMARY_TRANSPORT_CONNECT_FAILED = 0x0000010E,63 PRIMARY_TRANSPORT_CONNECT_FAILED = 0x0000010E,
82
83 /// The page fault was a transition fault.64 /// The page fault was a transition fault.
84 PAGE_FAULT_TRANSITION = 0x00000110,65 PAGE_FAULT_TRANSITION = 0x00000110,
85
86 /// The page fault was a demand zero fault.66 /// The page fault was a demand zero fault.
87 PAGE_FAULT_DEMAND_ZERO = 0x00000111,67 PAGE_FAULT_DEMAND_ZERO = 0x00000111,
88
89 /// The page fault was a demand zero fault.68 /// The page fault was a demand zero fault.
90 PAGE_FAULT_COPY_ON_WRITE = 0x00000112,69 PAGE_FAULT_COPY_ON_WRITE = 0x00000112,
91
92 /// The page fault was a demand zero fault.70 /// The page fault was a demand zero fault.
93 PAGE_FAULT_GUARD_PAGE = 0x00000113,71 PAGE_FAULT_GUARD_PAGE = 0x00000113,
94
95 /// The page fault was satisfied by reading from a secondary storage device.72 /// The page fault was satisfied by reading from a secondary storage device.
96 PAGE_FAULT_PAGING_FILE = 0x00000114,73 PAGE_FAULT_PAGING_FILE = 0x00000114,
97
98 /// The cached page was locked during operation.74 /// The cached page was locked during operation.
99 CACHE_PAGE_LOCKED = 0x00000115,75 CACHE_PAGE_LOCKED = 0x00000115,
100
101 /// The crash dump exists in a paging file.76 /// The crash dump exists in a paging file.
102 CRASH_DUMP = 0x00000116,77 CRASH_DUMP = 0x00000116,
103
104 /// The specified buffer contains all zeros.78 /// The specified buffer contains all zeros.
105 BUFFER_ALL_ZEROS = 0x00000117,79 BUFFER_ALL_ZEROS = 0x00000117,
106
107 /// A reparse should be performed by the Object Manager because the name of the file resulted in a symbolic link.80 /// A reparse should be performed by the Object Manager because the name of the file resulted in a symbolic link.
108 REPARSE_OBJECT = 0x00000118,81 REPARSE_OBJECT = 0x00000118,
109
110 /// The device has succeeded a query-stop and its resource requirements have changed.82 /// The device has succeeded a query-stop and its resource requirements have changed.
111 RESOURCE_REQUIREMENTS_CHANGED = 0x00000119,83 RESOURCE_REQUIREMENTS_CHANGED = 0x00000119,
112
113 /// The translator has translated these resources into the global space and no additional translations should be performed.84 /// The translator has translated these resources into the global space and no additional translations should be performed.
114 TRANSLATION_COMPLETE = 0x00000120,85 TRANSLATION_COMPLETE = 0x00000120,
115
116 /// The directory service evaluated group memberships locally, because it was unable to contact a global catalog server.86 /// The directory service evaluated group memberships locally, because it was unable to contact a global catalog server.
117 DS_MEMBERSHIP_EVALUATED_LOCALLY = 0x00000121,87 DS_MEMBERSHIP_EVALUATED_LOCALLY = 0x00000121,
118
119 /// A process being terminated has no threads to terminate.88 /// A process being terminated has no threads to terminate.
120 NOTHING_TO_TERMINATE = 0x00000122,89 NOTHING_TO_TERMINATE = 0x00000122,
121
122 /// The specified process is not part of a job.90 /// The specified process is not part of a job.
123 PROCESS_NOT_IN_JOB = 0x00000123,91 PROCESS_NOT_IN_JOB = 0x00000123,
124
125 /// The specified process is part of a job.92 /// The specified process is part of a job.
126 PROCESS_IN_JOB = 0x00000124,93 PROCESS_IN_JOB = 0x00000124,
127
128 /// {Volume Shadow Copy Service} The system is now ready for hibernation.94 /// {Volume Shadow Copy Service} The system is now ready for hibernation.
129 VOLSNAP_HIBERNATE_READY = 0x00000125,95 VOLSNAP_HIBERNATE_READY = 0x00000125,
130
131 /// A file system or file system filter driver has successfully completed an FsFilter operation.96 /// A file system or file system filter driver has successfully completed an FsFilter operation.
132 FSFILTER_OP_COMPLETED_SUCCESSFULLY = 0x00000126,97 FSFILTER_OP_COMPLETED_SUCCESSFULLY = 0x00000126,
133
134 /// The specified interrupt vector was already connected.98 /// The specified interrupt vector was already connected.
135 INTERRUPT_VECTOR_ALREADY_CONNECTED = 0x00000127,99 INTERRUPT_VECTOR_ALREADY_CONNECTED = 0x00000127,
136
137 /// The specified interrupt vector is still connected.100 /// The specified interrupt vector is still connected.
138 INTERRUPT_STILL_CONNECTED = 0x00000128,101 INTERRUPT_STILL_CONNECTED = 0x00000128,
139
140 /// The current process is a cloned process.102 /// The current process is a cloned process.
141 PROCESS_CLONED = 0x00000129,103 PROCESS_CLONED = 0x00000129,
142
143 /// The file was locked and all users of the file can only read.104 /// The file was locked and all users of the file can only read.
144 FILE_LOCKED_WITH_ONLY_READERS = 0x0000012A,105 FILE_LOCKED_WITH_ONLY_READERS = 0x0000012A,
145
146 /// The file was locked and at least one user of the file can write.106 /// The file was locked and at least one user of the file can write.
147 FILE_LOCKED_WITH_WRITERS = 0x0000012B,107 FILE_LOCKED_WITH_WRITERS = 0x0000012B,
148
149 /// The specified ResourceManager made no changes or updates to the resource under this transaction.108 /// The specified ResourceManager made no changes or updates to the resource under this transaction.
150 RESOURCEMANAGER_READ_ONLY = 0x00000202,109 RESOURCEMANAGER_READ_ONLY = 0x00000202,
151
152 /// An operation is blocked and waiting for an oplock.110 /// An operation is blocked and waiting for an oplock.
153 WAIT_FOR_OPLOCK = 0x00000367,111 WAIT_FOR_OPLOCK = 0x00000367,
154
155 /// Debugger handled the exception.112 /// Debugger handled the exception.
156 DBG_EXCEPTION_HANDLED = 0x00010001,113 DBG_EXCEPTION_HANDLED = 0x00010001,
157
158 /// The debugger continued.114 /// The debugger continued.
159 DBG_CONTINUE = 0x00010002,115 DBG_CONTINUE = 0x00010002,
160
161 /// The IO was completed by a filter.116 /// The IO was completed by a filter.
162 FLT_IO_COMPLETE = 0x001C0001,117 FLT_IO_COMPLETE = 0x001C0001,
163
164 /// The file is temporarily unavailable.118 /// The file is temporarily unavailable.
165 FILE_NOT_AVAILABLE = 0xC0000467,119 FILE_NOT_AVAILABLE = 0xC0000467,
166
167 /// The share is temporarily unavailable.120 /// The share is temporarily unavailable.
168 SHARE_UNAVAILABLE = 0xC0000480,121 SHARE_UNAVAILABLE = 0xC0000480,
169
170 /// A threadpool worker thread entered a callback at thread affinity %p and exited at affinity %p.122 /// A threadpool worker thread entered a callback at thread affinity %p and exited at affinity %p.
171 /// This is unexpected, indicating that the callback missed restoring the priority.123 /// This is unexpected, indicating that the callback missed restoring the priority.
172 CALLBACK_RETURNED_THREAD_AFFINITY = 0xC0000721,124 CALLBACK_RETURNED_THREAD_AFFINITY = 0xC0000721,
173
174 /// {Object Exists} An attempt was made to create an object but the object name already exists.125 /// {Object Exists} An attempt was made to create an object but the object name already exists.
175 OBJECT_NAME_EXISTS = 0x40000000,126 OBJECT_NAME_EXISTS = 0x40000000,
176
177 /// {Thread Suspended} A thread termination occurred while the thread was suspended. The thread resumed, and termination proceeded.127 /// {Thread Suspended} A thread termination occurred while the thread was suspended. The thread resumed, and termination proceeded.
178 THREAD_WAS_SUSPENDED = 0x40000001,128 THREAD_WAS_SUSPENDED = 0x40000001,
179
180 /// {Working Set Range Error} An attempt was made to set the working set minimum or maximum to values that are outside the allowable range.129 /// {Working Set Range Error} An attempt was made to set the working set minimum or maximum to values that are outside the allowable range.
181 WORKING_SET_LIMIT_RANGE = 0x40000002,130 WORKING_SET_LIMIT_RANGE = 0x40000002,
182
183 /// {Image Relocated} An image file could not be mapped at the address that is specified in the image file. Local fixes must be performed on this image.131 /// {Image Relocated} An image file could not be mapped at the address that is specified in the image file. Local fixes must be performed on this image.
184 IMAGE_NOT_AT_BASE = 0x40000003,132 IMAGE_NOT_AT_BASE = 0x40000003,
185
186 /// This informational level status indicates that a specified registry subtree transaction state did not yet exist and had to be created.133 /// This informational level status indicates that a specified registry subtree transaction state did not yet exist and had to be created.
187 RXACT_STATE_CREATED = 0x40000004,134 RXACT_STATE_CREATED = 0x40000004,
188
189 /// {Segment Load} A virtual DOS machine (VDM) is loading, unloading, or moving an MS-DOS or Win16 program segment image.135 /// {Segment Load} A virtual DOS machine (VDM) is loading, unloading, or moving an MS-DOS or Win16 program segment image.
190 /// An exception is raised so that a debugger can load, unload, or track symbols and breakpoints within these 16-bit segments.136 /// An exception is raised so that a debugger can load, unload, or track symbols and breakpoints within these 16-bit segments.
191 SEGMENT_NOTIFICATION = 0x40000005,137 SEGMENT_NOTIFICATION = 0x40000005,
192
193 /// {Local Session Key} A user session key was requested for a local remote procedure call (RPC) connection.138 /// {Local Session Key} A user session key was requested for a local remote procedure call (RPC) connection.
194 /// The session key that is returned is a constant value and not unique to this connection.139 /// The session key that is returned is a constant value and not unique to this connection.
195 LOCAL_USER_SESSION_KEY = 0x40000006,140 LOCAL_USER_SESSION_KEY = 0x40000006,
196
197 /// {Invalid Current Directory} The process cannot switch to the startup current directory %hs.141 /// {Invalid Current Directory} The process cannot switch to the startup current directory %hs.
198 /// Select OK to set the current directory to %hs, or select CANCEL to exit.142 /// Select OK to set the current directory to %hs, or select CANCEL to exit.
199 BAD_CURRENT_DIRECTORY = 0x40000007,143 BAD_CURRENT_DIRECTORY = 0x40000007,
200
201 /// {Serial IOCTL Complete} A serial I/O operation was completed by another write to a serial port. (The IOCTL_SERIAL_XOFF_COUNTER reached zero.)144 /// {Serial IOCTL Complete} A serial I/O operation was completed by another write to a serial port. (The IOCTL_SERIAL_XOFF_COUNTER reached zero.)
202 SERIAL_MORE_WRITES = 0x40000008,145 SERIAL_MORE_WRITES = 0x40000008,
203
204 /// {Registry Recovery} One of the files that contains the system registry data had to be recovered by using a log or alternate copy. The recovery was successful.146 /// {Registry Recovery} One of the files that contains the system registry data had to be recovered by using a log or alternate copy. The recovery was successful.
205 REGISTRY_RECOVERED = 0x40000009,147 REGISTRY_RECOVERED = 0x40000009,
206
207 /// {Redundant Read} To satisfy a read request, the Windows NT operating system fault-tolerant file system successfully read the requested data from a redundant copy.148 /// {Redundant Read} To satisfy a read request, the Windows NT operating system fault-tolerant file system successfully read the requested data from a redundant copy.
208 /// This was done because the file system encountered a failure on a member of the fault-tolerant volume but was unable to reassign the failing area of the device.149 /// This was done because the file system encountered a failure on a member of the fault-tolerant volume but was unable to reassign the failing area of the device.
209 FT_READ_RECOVERY_FROM_BACKUP = 0x4000000A,150 FT_READ_RECOVERY_FROM_BACKUP = 0x4000000A,
210
211 /// {Redundant Write} To satisfy a write request, the Windows NT fault-tolerant file system successfully wrote a redundant copy of the information.151 /// {Redundant Write} To satisfy a write request, the Windows NT fault-tolerant file system successfully wrote a redundant copy of the information.
212 /// This was done because the file system encountered a failure on a member of the fault-tolerant volume but was unable to reassign the failing area of the device.152 /// This was done because the file system encountered a failure on a member of the fault-tolerant volume but was unable to reassign the failing area of the device.
213 FT_WRITE_RECOVERY = 0x4000000B,153 FT_WRITE_RECOVERY = 0x4000000B,
214
215 /// {Serial IOCTL Timeout} A serial I/O operation completed because the time-out period expired.154 /// {Serial IOCTL Timeout} A serial I/O operation completed because the time-out period expired.
216 /// (The IOCTL_SERIAL_XOFF_COUNTER had not reached zero.)155 /// (The IOCTL_SERIAL_XOFF_COUNTER had not reached zero.)
217 SERIAL_COUNTER_TIMEOUT = 0x4000000C,156 SERIAL_COUNTER_TIMEOUT = 0x4000000C,
218
219 /// {Password Too Complex} The Windows password is too complex to be converted to a LAN Manager password.157 /// {Password Too Complex} The Windows password is too complex to be converted to a LAN Manager password.
220 /// The LAN Manager password that returned is a NULL string.158 /// The LAN Manager password that returned is a NULL string.
221 NULL_LM_PASSWORD = 0x4000000D,159 NULL_LM_PASSWORD = 0x4000000D,
222
223 /// {Machine Type Mismatch} The image file %hs is valid but is for a machine type other than the current machine.160 /// {Machine Type Mismatch} The image file %hs is valid but is for a machine type other than the current machine.
224 /// Select OK to continue, or CANCEL to fail the DLL load.161 /// Select OK to continue, or CANCEL to fail the DLL load.
225 IMAGE_MACHINE_TYPE_MISMATCH = 0x4000000E,162 IMAGE_MACHINE_TYPE_MISMATCH = 0x4000000E,
226
227 /// {Partial Data Received} The network transport returned partial data to its client. The remaining data will be sent later.163 /// {Partial Data Received} The network transport returned partial data to its client. The remaining data will be sent later.
228 RECEIVE_PARTIAL = 0x4000000F,164 RECEIVE_PARTIAL = 0x4000000F,
229
230 /// {Expedited Data Received} The network transport returned data to its client that was marked as expedited by the remote system.165 /// {Expedited Data Received} The network transport returned data to its client that was marked as expedited by the remote system.
231 RECEIVE_EXPEDITED = 0x40000010,166 RECEIVE_EXPEDITED = 0x40000010,
232
233 /// {Partial Expedited Data Received} The network transport returned partial data to its client and this data was marked as expedited by the remote system. The remaining data will be sent later.167 /// {Partial Expedited Data Received} The network transport returned partial data to its client and this data was marked as expedited by the remote system. The remaining data will be sent later.
234 RECEIVE_PARTIAL_EXPEDITED = 0x40000011,168 RECEIVE_PARTIAL_EXPEDITED = 0x40000011,
235
236 /// {TDI Event Done} The TDI indication has completed successfully.169 /// {TDI Event Done} The TDI indication has completed successfully.
237 EVENT_DONE = 0x40000012,170 EVENT_DONE = 0x40000012,
238
239 /// {TDI Event Pending} The TDI indication has entered the pending state.171 /// {TDI Event Pending} The TDI indication has entered the pending state.
240 EVENT_PENDING = 0x40000013,172 EVENT_PENDING = 0x40000013,
241
242 /// Checking file system on %wZ.173 /// Checking file system on %wZ.
243 CHECKING_FILE_SYSTEM = 0x40000014,174 CHECKING_FILE_SYSTEM = 0x40000014,
244
245 /// {Fatal Application Exit} %hs175 /// {Fatal Application Exit} %hs
246 FATAL_APP_EXIT = 0x40000015,176 FATAL_APP_EXIT = 0x40000015,
247
248 /// The specified registry key is referenced by a predefined handle.177 /// The specified registry key is referenced by a predefined handle.
249 PREDEFINED_HANDLE = 0x40000016,178 PREDEFINED_HANDLE = 0x40000016,
250
251 /// {Page Unlocked} The page protection of a locked page was changed to 'No Access' and the page was unlocked from memory and from the process.179 /// {Page Unlocked} The page protection of a locked page was changed to 'No Access' and the page was unlocked from memory and from the process.
252 WAS_UNLOCKED = 0x40000017,180 WAS_UNLOCKED = 0x40000017,
253
254 /// %hs181 /// %hs
255 SERVICE_NOTIFICATION = 0x40000018,182 SERVICE_NOTIFICATION = 0x40000018,
256
257 /// {Page Locked} One of the pages to lock was already locked.183 /// {Page Locked} One of the pages to lock was already locked.
258 WAS_LOCKED = 0x40000019,184 WAS_LOCKED = 0x40000019,
259
260 /// Application popup: %1 : %2185 /// Application popup: %1 : %2
261 LOG_HARD_ERROR = 0x4000001A,186 LOG_HARD_ERROR = 0x4000001A,
262
263 /// A Win32 process already exists.187 /// A Win32 process already exists.
264 ALREADY_WIN32 = 0x4000001B,188 ALREADY_WIN32 = 0x4000001B,
265
266 /// An exception status code that is used by the Win32 x86 emulation subsystem.189 /// An exception status code that is used by the Win32 x86 emulation subsystem.
267 WX86_UNSIMULATE = 0x4000001C,190 WX86_UNSIMULATE = 0x4000001C,
268
269 /// An exception status code that is used by the Win32 x86 emulation subsystem.191 /// An exception status code that is used by the Win32 x86 emulation subsystem.
270 WX86_CONTINUE = 0x4000001D,192 WX86_CONTINUE = 0x4000001D,
271
272 /// An exception status code that is used by the Win32 x86 emulation subsystem.193 /// An exception status code that is used by the Win32 x86 emulation subsystem.
273 WX86_SINGLE_STEP = 0x4000001E,194 WX86_SINGLE_STEP = 0x4000001E,
274
275 /// An exception status code that is used by the Win32 x86 emulation subsystem.195 /// An exception status code that is used by the Win32 x86 emulation subsystem.
276 WX86_BREAKPOINT = 0x4000001F,196 WX86_BREAKPOINT = 0x4000001F,
277
278 /// An exception status code that is used by the Win32 x86 emulation subsystem.197 /// An exception status code that is used by the Win32 x86 emulation subsystem.
279 WX86_EXCEPTION_CONTINUE = 0x40000020,198 WX86_EXCEPTION_CONTINUE = 0x40000020,
280
281 /// An exception status code that is used by the Win32 x86 emulation subsystem.199 /// An exception status code that is used by the Win32 x86 emulation subsystem.
282 WX86_EXCEPTION_LASTCHANCE = 0x40000021,200 WX86_EXCEPTION_LASTCHANCE = 0x40000021,
283
284 /// An exception status code that is used by the Win32 x86 emulation subsystem.201 /// An exception status code that is used by the Win32 x86 emulation subsystem.
285 WX86_EXCEPTION_CHAIN = 0x40000022,202 WX86_EXCEPTION_CHAIN = 0x40000022,
286
287 /// {Machine Type Mismatch} The image file %hs is valid but is for a machine type other than the current machine.203 /// {Machine Type Mismatch} The image file %hs is valid but is for a machine type other than the current machine.
288 IMAGE_MACHINE_TYPE_MISMATCH_EXE = 0x40000023,204 IMAGE_MACHINE_TYPE_MISMATCH_EXE = 0x40000023,
289
290 /// A yield execution was performed and no thread was available to run.205 /// A yield execution was performed and no thread was available to run.
291 NO_YIELD_PERFORMED = 0x40000024,206 NO_YIELD_PERFORMED = 0x40000024,
292
293 /// The resume flag to a timer API was ignored.207 /// The resume flag to a timer API was ignored.
294 TIMER_RESUME_IGNORED = 0x40000025,208 TIMER_RESUME_IGNORED = 0x40000025,
295
296 /// The arbiter has deferred arbitration of these resources to its parent.209 /// The arbiter has deferred arbitration of these resources to its parent.
297 ARBITRATION_UNHANDLED = 0x40000026,210 ARBITRATION_UNHANDLED = 0x40000026,
298
299 /// The device has detected a CardBus card in its slot.211 /// The device has detected a CardBus card in its slot.
300 CARDBUS_NOT_SUPPORTED = 0x40000027,212 CARDBUS_NOT_SUPPORTED = 0x40000027,
301
302 /// An exception status code that is used by the Win32 x86 emulation subsystem.213 /// An exception status code that is used by the Win32 x86 emulation subsystem.
303 WX86_CREATEWX86TIB = 0x40000028,214 WX86_CREATEWX86TIB = 0x40000028,
304
305 /// The CPUs in this multiprocessor system are not all the same revision level.215 /// The CPUs in this multiprocessor system are not all the same revision level.
306 /// To use all processors, the operating system restricts itself to the features of the least capable processor in the system.216 /// To use all processors, the operating system restricts itself to the features of the least capable processor in the system.
307 /// If problems occur with this system, contact the CPU manufacturer to see if this mix of processors is supported.217 /// If problems occur with this system, contact the CPU manufacturer to see if this mix of processors is supported.
308 MP_PROCESSOR_MISMATCH = 0x40000029,218 MP_PROCESSOR_MISMATCH = 0x40000029,
309
310 /// The system was put into hibernation.219 /// The system was put into hibernation.
311 HIBERNATED = 0x4000002A,220 HIBERNATED = 0x4000002A,
312
313 /// The system was resumed from hibernation.221 /// The system was resumed from hibernation.
314 RESUME_HIBERNATION = 0x4000002B,222 RESUME_HIBERNATION = 0x4000002B,
315
316 /// Windows has detected that the system firmware (BIOS) was updated [previous firmware date = %2, current firmware date %3].223 /// Windows has detected that the system firmware (BIOS) was updated [previous firmware date = %2, current firmware date %3].
317 FIRMWARE_UPDATED = 0x4000002C,224 FIRMWARE_UPDATED = 0x4000002C,
318
319 /// A device driver is leaking locked I/O pages and is causing system degradation.225 /// A device driver is leaking locked I/O pages and is causing system degradation.
320 /// The system has automatically enabled the tracking code to try and catch the culprit.226 /// The system has automatically enabled the tracking code to try and catch the culprit.
321 DRIVERS_LEAKING_LOCKED_PAGES = 0x4000002D,227 DRIVERS_LEAKING_LOCKED_PAGES = 0x4000002D,
322
323 /// The ALPC message being canceled has already been retrieved from the queue on the other side.228 /// The ALPC message being canceled has already been retrieved from the queue on the other side.
324 MESSAGE_RETRIEVED = 0x4000002E,229 MESSAGE_RETRIEVED = 0x4000002E,
325
326 /// The system power state is transitioning from %2 to %3.230 /// The system power state is transitioning from %2 to %3.
327 SYSTEM_POWERSTATE_TRANSITION = 0x4000002F,231 SYSTEM_POWERSTATE_TRANSITION = 0x4000002F,
328
329 /// The receive operation was successful.232 /// The receive operation was successful.
330 /// Check the ALPC completion list for the received message.233 /// Check the ALPC completion list for the received message.
331 ALPC_CHECK_COMPLETION_LIST = 0x40000030,234 ALPC_CHECK_COMPLETION_LIST = 0x40000030,
332
333 /// The system power state is transitioning from %2 to %3 but could enter %4.235 /// The system power state is transitioning from %2 to %3 but could enter %4.
334 SYSTEM_POWERSTATE_COMPLEX_TRANSITION = 0x40000031,236 SYSTEM_POWERSTATE_COMPLEX_TRANSITION = 0x40000031,
335
336 /// Access to %1 is monitored by policy rule %2.237 /// Access to %1 is monitored by policy rule %2.
337 ACCESS_AUDIT_BY_POLICY = 0x40000032,238 ACCESS_AUDIT_BY_POLICY = 0x40000032,
338
339 /// A valid hibernation file has been invalidated and should be abandoned.239 /// A valid hibernation file has been invalidated and should be abandoned.
340 ABANDON_HIBERFILE = 0x40000033,240 ABANDON_HIBERFILE = 0x40000033,
341
342 /// Business rule scripts are disabled for the calling application.241 /// Business rule scripts are disabled for the calling application.
343 BIZRULES_NOT_ENABLED = 0x40000034,242 BIZRULES_NOT_ENABLED = 0x40000034,
344
345 /// The system has awoken.243 /// The system has awoken.
346 WAKE_SYSTEM = 0x40000294,244 WAKE_SYSTEM = 0x40000294,
347
348 /// The directory service is shutting down.245 /// The directory service is shutting down.
349 DS_SHUTTING_DOWN = 0x40000370,246 DS_SHUTTING_DOWN = 0x40000370,
350
351 /// Debugger will reply later.247 /// Debugger will reply later.
352 DBG_REPLY_LATER = 0x40010001,248 DBG_REPLY_LATER = 0x40010001,
353
354 /// Debugger cannot provide a handle.249 /// Debugger cannot provide a handle.
355 DBG_UNABLE_TO_PROVIDE_HANDLE = 0x40010002,250 DBG_UNABLE_TO_PROVIDE_HANDLE = 0x40010002,
356
357 /// Debugger terminated the thread.251 /// Debugger terminated the thread.
358 DBG_TERMINATE_THREAD = 0x40010003,252 DBG_TERMINATE_THREAD = 0x40010003,
359
360 /// Debugger terminated the process.253 /// Debugger terminated the process.
361 DBG_TERMINATE_PROCESS = 0x40010004,254 DBG_TERMINATE_PROCESS = 0x40010004,
362
363 /// Debugger obtained control of C.255 /// Debugger obtained control of C.
364 DBG_CONTROL_C = 0x40010005,256 DBG_CONTROL_C = 0x40010005,
365
366 /// Debugger printed an exception on control C.257 /// Debugger printed an exception on control C.
367 DBG_PRINTEXCEPTION_C = 0x40010006,258 DBG_PRINTEXCEPTION_C = 0x40010006,
368
369 /// Debugger received a RIP exception.259 /// Debugger received a RIP exception.
370 DBG_RIPEXCEPTION = 0x40010007,260 DBG_RIPEXCEPTION = 0x40010007,
371
372 /// Debugger received a control break.261 /// Debugger received a control break.
373 DBG_CONTROL_BREAK = 0x40010008,262 DBG_CONTROL_BREAK = 0x40010008,
374
375 /// Debugger command communication exception.263 /// Debugger command communication exception.
376 DBG_COMMAND_EXCEPTION = 0x40010009,264 DBG_COMMAND_EXCEPTION = 0x40010009,
377
378 /// A UUID that is valid only on this computer has been allocated.265 /// A UUID that is valid only on this computer has been allocated.
379 RPC_NT_UUID_LOCAL_ONLY = 0x40020056,266 RPC_NT_UUID_LOCAL_ONLY = 0x40020056,
380
381 /// Some data remains to be sent in the request buffer.267 /// Some data remains to be sent in the request buffer.
382 RPC_NT_SEND_INCOMPLETE = 0x400200AF,268 RPC_NT_SEND_INCOMPLETE = 0x400200AF,
383
384 /// The Client Drive Mapping Service has connected on Terminal Connection.269 /// The Client Drive Mapping Service has connected on Terminal Connection.
385 CTX_CDM_CONNECT = 0x400A0004,270 CTX_CDM_CONNECT = 0x400A0004,
386
387 /// The Client Drive Mapping Service has disconnected on Terminal Connection.271 /// The Client Drive Mapping Service has disconnected on Terminal Connection.
388 CTX_CDM_DISCONNECT = 0x400A0005,272 CTX_CDM_DISCONNECT = 0x400A0005,
389
390 /// A kernel mode component is releasing a reference on an activation context.273 /// A kernel mode component is releasing a reference on an activation context.
391 SXS_RELEASE_ACTIVATION_CONTEXT = 0x4015000D,274 SXS_RELEASE_ACTIVATION_CONTEXT = 0x4015000D,
392
393 /// The transactional resource manager is already consistent. Recovery is not needed.275 /// The transactional resource manager is already consistent. Recovery is not needed.
394 RECOVERY_NOT_NEEDED = 0x40190034,276 RECOVERY_NOT_NEEDED = 0x40190034,
395
396 /// The transactional resource manager has already been started.277 /// The transactional resource manager has already been started.
397 RM_ALREADY_STARTED = 0x40190035,278 RM_ALREADY_STARTED = 0x40190035,
398
399 /// The log service encountered a log stream with no restart area.279 /// The log service encountered a log stream with no restart area.
400 LOG_NO_RESTART = 0x401A000C,280 LOG_NO_RESTART = 0x401A000C,
401
402 /// {Display Driver Recovered From Failure} The %hs display driver has detected a failure and recovered from it. Some graphical operations might have failed.281 /// {Display Driver Recovered From Failure} The %hs display driver has detected a failure and recovered from it. Some graphical operations might have failed.
403 /// The next time you restart the machine, a dialog box appears, giving you an opportunity to upload data about this failure to Microsoft.282 /// The next time you restart the machine, a dialog box appears, giving you an opportunity to upload data about this failure to Microsoft.
404 VIDEO_DRIVER_DEBUG_REPORT_REQUEST = 0x401B00EC,283 VIDEO_DRIVER_DEBUG_REPORT_REQUEST = 0x401B00EC,
405
406 /// The specified buffer is not big enough to contain the entire requested dataset.284 /// The specified buffer is not big enough to contain the entire requested dataset.
407 /// Partial data is populated up to the size of the buffer.285 /// Partial data is populated up to the size of the buffer.
408 /// The caller needs to provide a buffer of the size as specified in the partially populated buffer's content (interface specific).286 /// The caller needs to provide a buffer of the size as specified in the partially populated buffer's content (interface specific).
409 GRAPHICS_PARTIAL_DATA_POPULATED = 0x401E000A,287 GRAPHICS_PARTIAL_DATA_POPULATED = 0x401E000A,
410
411 /// The kernel driver detected a version mismatch between it and the user mode driver.288 /// The kernel driver detected a version mismatch between it and the user mode driver.
412 GRAPHICS_DRIVER_MISMATCH = 0x401E0117,289 GRAPHICS_DRIVER_MISMATCH = 0x401E0117,
413
414 /// No mode is pinned on the specified VidPN source/target.290 /// No mode is pinned on the specified VidPN source/target.
415 GRAPHICS_MODE_NOT_PINNED = 0x401E0307,291 GRAPHICS_MODE_NOT_PINNED = 0x401E0307,
416
417 /// The specified mode set does not specify a preference for one of its modes.292 /// The specified mode set does not specify a preference for one of its modes.
418 GRAPHICS_NO_PREFERRED_MODE = 0x401E031E,293 GRAPHICS_NO_PREFERRED_MODE = 0x401E031E,
419
420 /// The specified dataset (for example, mode set, frequency range set, descriptor set, or topology) is empty.294 /// The specified dataset (for example, mode set, frequency range set, descriptor set, or topology) is empty.
421 GRAPHICS_DATASET_IS_EMPTY = 0x401E034B,295 GRAPHICS_DATASET_IS_EMPTY = 0x401E034B,
422
423 /// The specified dataset (for example, mode set, frequency range set, descriptor set, or topology) does not contain any more elements.296 /// The specified dataset (for example, mode set, frequency range set, descriptor set, or topology) does not contain any more elements.
424 GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET = 0x401E034C,297 GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET = 0x401E034C,
425
426 /// The specified content transformation is not pinned on the specified VidPN present path.298 /// The specified content transformation is not pinned on the specified VidPN present path.
427 GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED = 0x401E0351,299 GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED = 0x401E0351,
428
429 /// The child device presence was not reliably detected.300 /// The child device presence was not reliably detected.
430 GRAPHICS_UNKNOWN_CHILD_STATUS = 0x401E042F,301 GRAPHICS_UNKNOWN_CHILD_STATUS = 0x401E042F,
431
432 /// Starting the lead adapter in a linked configuration has been temporarily deferred.302 /// Starting the lead adapter in a linked configuration has been temporarily deferred.
433 GRAPHICS_LEADLINK_START_DEFERRED = 0x401E0437,303 GRAPHICS_LEADLINK_START_DEFERRED = 0x401E0437,
434
435 /// The display adapter is being polled for children too frequently at the same polling level.304 /// The display adapter is being polled for children too frequently at the same polling level.
436 GRAPHICS_POLLING_TOO_FREQUENTLY = 0x401E0439,305 GRAPHICS_POLLING_TOO_FREQUENTLY = 0x401E0439,
437
438 /// Starting the adapter has been temporarily deferred.306 /// Starting the adapter has been temporarily deferred.
439 GRAPHICS_START_DEFERRED = 0x401E043A,307 GRAPHICS_START_DEFERRED = 0x401E043A,
440
441 /// The request will be completed later by an NDIS status indication.308 /// The request will be completed later by an NDIS status indication.
442 NDIS_INDICATION_REQUIRED = 0x40230001,309 NDIS_INDICATION_REQUIRED = 0x40230001,
443
444 /// {EXCEPTION} Guard Page Exception A page of memory that marks the end of a data structure, such as a stack or an array, has been accessed.310 /// {EXCEPTION} Guard Page Exception A page of memory that marks the end of a data structure, such as a stack or an array, has been accessed.
445 GUARD_PAGE_VIOLATION = 0x80000001,311 GUARD_PAGE_VIOLATION = 0x80000001,
446
447 /// {EXCEPTION} Alignment Fault A data type misalignment was detected in a load or store instruction.312 /// {EXCEPTION} Alignment Fault A data type misalignment was detected in a load or store instruction.
448 DATATYPE_MISALIGNMENT = 0x80000002,313 DATATYPE_MISALIGNMENT = 0x80000002,
449
450 /// {EXCEPTION} Breakpoint A breakpoint has been reached.314 /// {EXCEPTION} Breakpoint A breakpoint has been reached.
451 BREAKPOINT = 0x80000003,315 BREAKPOINT = 0x80000003,
452
453 /// {EXCEPTION} Single Step A single step or trace operation has just been completed.316 /// {EXCEPTION} Single Step A single step or trace operation has just been completed.
454 SINGLE_STEP = 0x80000004,317 SINGLE_STEP = 0x80000004,
455
456 /// {Buffer Overflow} The data was too large to fit into the specified buffer.318 /// {Buffer Overflow} The data was too large to fit into the specified buffer.
457 BUFFER_OVERFLOW = 0x80000005,319 BUFFER_OVERFLOW = 0x80000005,
458
459 /// {No More Files} No more files were found which match the file specification.320 /// {No More Files} No more files were found which match the file specification.
460 NO_MORE_FILES = 0x80000006,321 NO_MORE_FILES = 0x80000006,
461
462 /// {Kernel Debugger Awakened} The system debugger was awakened by an interrupt.322 /// {Kernel Debugger Awakened} The system debugger was awakened by an interrupt.
463 WAKE_SYSTEM_DEBUGGER = 0x80000007,323 WAKE_SYSTEM_DEBUGGER = 0x80000007,
464
465 /// {Handles Closed} Handles to objects have been automatically closed because of the requested operation.324 /// {Handles Closed} Handles to objects have been automatically closed because of the requested operation.
466 HANDLES_CLOSED = 0x8000000A,325 HANDLES_CLOSED = 0x8000000A,
467
468 /// {Non-Inheritable ACL} An access control list (ACL) contains no components that can be inherited.326 /// {Non-Inheritable ACL} An access control list (ACL) contains no components that can be inherited.
469 NO_INHERITANCE = 0x8000000B,327 NO_INHERITANCE = 0x8000000B,
470
471 /// {GUID Substitution} During the translation of a globally unique identifier (GUID) to a Windows security ID (SID), no administratively defined GUID prefix was found.328 /// {GUID Substitution} During the translation of a globally unique identifier (GUID) to a Windows security ID (SID), no administratively defined GUID prefix was found.
472 /// A substitute prefix was used, which will not compromise system security.329 /// A substitute prefix was used, which will not compromise system security.
473 /// However, this might provide a more restrictive access than intended.330 /// However, this might provide a more restrictive access than intended.
474 GUID_SUBSTITUTION_MADE = 0x8000000C,331 GUID_SUBSTITUTION_MADE = 0x8000000C,
475
476 /// Because of protection conflicts, not all the requested bytes could be copied.332 /// Because of protection conflicts, not all the requested bytes could be copied.
477 PARTIAL_COPY = 0x8000000D,333 PARTIAL_COPY = 0x8000000D,
478
479 /// {Out of Paper} The printer is out of paper.334 /// {Out of Paper} The printer is out of paper.
480 DEVICE_PAPER_EMPTY = 0x8000000E,335 DEVICE_PAPER_EMPTY = 0x8000000E,
481
482 /// {Device Power Is Off} The printer power has been turned off.336 /// {Device Power Is Off} The printer power has been turned off.
483 DEVICE_POWERED_OFF = 0x8000000F,337 DEVICE_POWERED_OFF = 0x8000000F,
484
485 /// {Device Offline} The printer has been taken offline.338 /// {Device Offline} The printer has been taken offline.
486 DEVICE_OFF_LINE = 0x80000010,339 DEVICE_OFF_LINE = 0x80000010,
487
488 /// {Device Busy} The device is currently busy.340 /// {Device Busy} The device is currently busy.
489 DEVICE_BUSY = 0x80000011,341 DEVICE_BUSY = 0x80000011,
490
491 /// {No More EAs} No more extended attributes (EAs) were found for the file.342 /// {No More EAs} No more extended attributes (EAs) were found for the file.
492 NO_MORE_EAS = 0x80000012,343 NO_MORE_EAS = 0x80000012,
493
494 /// {Illegal EA} The specified extended attribute (EA) name contains at least one illegal character.344 /// {Illegal EA} The specified extended attribute (EA) name contains at least one illegal character.
495 INVALID_EA_NAME = 0x80000013,345 INVALID_EA_NAME = 0x80000013,
496
497 /// {Inconsistent EA List} The extended attribute (EA) list is inconsistent.346 /// {Inconsistent EA List} The extended attribute (EA) list is inconsistent.
498 EA_LIST_INCONSISTENT = 0x80000014,347 EA_LIST_INCONSISTENT = 0x80000014,
499
500 /// {Invalid EA Flag} An invalid extended attribute (EA) flag was set.348 /// {Invalid EA Flag} An invalid extended attribute (EA) flag was set.
501 INVALID_EA_FLAG = 0x80000015,349 INVALID_EA_FLAG = 0x80000015,
502
503 /// {Verifying Disk} The media has changed and a verify operation is in progress; therefore, no reads or writes can be performed to the device, except those that are used in the verify operation.350 /// {Verifying Disk} The media has changed and a verify operation is in progress; therefore, no reads or writes can be performed to the device, except those that are used in the verify operation.
504 VERIFY_REQUIRED = 0x80000016,351 VERIFY_REQUIRED = 0x80000016,
505
506 /// {Too Much Information} The specified access control list (ACL) contained more information than was expected.352 /// {Too Much Information} The specified access control list (ACL) contained more information than was expected.
507 EXTRANEOUS_INFORMATION = 0x80000017,353 EXTRANEOUS_INFORMATION = 0x80000017,
508
509 /// This warning level status indicates that the transaction state already exists for the registry subtree, but that a transaction commit was previously aborted.354 /// This warning level status indicates that the transaction state already exists for the registry subtree, but that a transaction commit was previously aborted.
510 /// The commit has NOT been completed but has not been rolled back either; therefore, it can still be committed, if needed.355 /// The commit has NOT been completed but has not been rolled back either; therefore, it can still be committed, if needed.
511 RXACT_COMMIT_NECESSARY = 0x80000018,356 RXACT_COMMIT_NECESSARY = 0x80000018,
512
513 /// {No More Entries} No more entries are available from an enumeration operation.357 /// {No More Entries} No more entries are available from an enumeration operation.
514 NO_MORE_ENTRIES = 0x8000001A,358 NO_MORE_ENTRIES = 0x8000001A,
515
516 /// {Filemark Found} A filemark was detected.359 /// {Filemark Found} A filemark was detected.
517 FILEMARK_DETECTED = 0x8000001B,360 FILEMARK_DETECTED = 0x8000001B,
518
519 /// {Media Changed} The media has changed.361 /// {Media Changed} The media has changed.
520 MEDIA_CHANGED = 0x8000001C,362 MEDIA_CHANGED = 0x8000001C,
521
522 /// {I/O Bus Reset} An I/O bus reset was detected.363 /// {I/O Bus Reset} An I/O bus reset was detected.
523 BUS_RESET = 0x8000001D,364 BUS_RESET = 0x8000001D,
524
525 /// {End of Media} The end of the media was encountered.365 /// {End of Media} The end of the media was encountered.
526 END_OF_MEDIA = 0x8000001E,366 END_OF_MEDIA = 0x8000001E,
527
528 /// The beginning of a tape or partition has been detected.367 /// The beginning of a tape or partition has been detected.
529 BEGINNING_OF_MEDIA = 0x8000001F,368 BEGINNING_OF_MEDIA = 0x8000001F,
530
531 /// {Media Changed} The media might have changed.369 /// {Media Changed} The media might have changed.
532 MEDIA_CHECK = 0x80000020,370 MEDIA_CHECK = 0x80000020,
533
534 /// A tape access reached a set mark.371 /// A tape access reached a set mark.
535 SETMARK_DETECTED = 0x80000021,372 SETMARK_DETECTED = 0x80000021,
536
537 /// During a tape access, the end of the data written is reached.373 /// During a tape access, the end of the data written is reached.
538 NO_DATA_DETECTED = 0x80000022,374 NO_DATA_DETECTED = 0x80000022,
539
540 /// The redirector is in use and cannot be unloaded.375 /// The redirector is in use and cannot be unloaded.
541 REDIRECTOR_HAS_OPEN_HANDLES = 0x80000023,376 REDIRECTOR_HAS_OPEN_HANDLES = 0x80000023,
542
543 /// The server is in use and cannot be unloaded.377 /// The server is in use and cannot be unloaded.
544 SERVER_HAS_OPEN_HANDLES = 0x80000024,378 SERVER_HAS_OPEN_HANDLES = 0x80000024,
545
546 /// The specified connection has already been disconnected.379 /// The specified connection has already been disconnected.
547 ALREADY_DISCONNECTED = 0x80000025,380 ALREADY_DISCONNECTED = 0x80000025,
548
549 /// A long jump has been executed.381 /// A long jump has been executed.
550 LONGJUMP = 0x80000026,382 LONGJUMP = 0x80000026,
551
552 /// A cleaner cartridge is present in the tape library.383 /// A cleaner cartridge is present in the tape library.
553 CLEANER_CARTRIDGE_INSTALLED = 0x80000027,384 CLEANER_CARTRIDGE_INSTALLED = 0x80000027,
554
555 /// The Plug and Play query operation was not successful.385 /// The Plug and Play query operation was not successful.
556 PLUGPLAY_QUERY_VETOED = 0x80000028,386 PLUGPLAY_QUERY_VETOED = 0x80000028,
557
558 /// A frame consolidation has been executed.387 /// A frame consolidation has been executed.
559 UNWIND_CONSOLIDATE = 0x80000029,388 UNWIND_CONSOLIDATE = 0x80000029,
560
561 /// {Registry Hive Recovered} The registry hive (file): %hs was corrupted and it has been recovered. Some data might have been lost.389 /// {Registry Hive Recovered} The registry hive (file): %hs was corrupted and it has been recovered. Some data might have been lost.
562 REGISTRY_HIVE_RECOVERED = 0x8000002A,390 REGISTRY_HIVE_RECOVERED = 0x8000002A,
563
564 /// The application is attempting to run executable code from the module %hs. This might be insecure.391 /// The application is attempting to run executable code from the module %hs. This might be insecure.
565 /// An alternative, %hs, is available. Should the application use the secure module %hs?392 /// An alternative, %hs, is available. Should the application use the secure module %hs?
566 DLL_MIGHT_BE_INSECURE = 0x8000002B,393 DLL_MIGHT_BE_INSECURE = 0x8000002B,
567
568 /// The application is loading executable code from the module %hs.394 /// The application is loading executable code from the module %hs.
569 /// This is secure but might be incompatible with previous releases of the operating system.395 /// This is secure but might be incompatible with previous releases of the operating system.
570 /// An alternative, %hs, is available. Should the application use the secure module %hs?396 /// An alternative, %hs, is available. Should the application use the secure module %hs?
571 DLL_MIGHT_BE_INCOMPATIBLE = 0x8000002C,397 DLL_MIGHT_BE_INCOMPATIBLE = 0x8000002C,
572
573 /// The create operation stopped after reaching a symbolic link.398 /// The create operation stopped after reaching a symbolic link.
574 STOPPED_ON_SYMLINK = 0x8000002D,399 STOPPED_ON_SYMLINK = 0x8000002D,
575
576 /// The device has indicated that cleaning is necessary.400 /// The device has indicated that cleaning is necessary.
577 DEVICE_REQUIRES_CLEANING = 0x80000288,401 DEVICE_REQUIRES_CLEANING = 0x80000288,
578
579 /// The device has indicated that its door is open. Further operations require it closed and secured.402 /// The device has indicated that its door is open. Further operations require it closed and secured.
580 DEVICE_DOOR_OPEN = 0x80000289,403 DEVICE_DOOR_OPEN = 0x80000289,
581
582 /// Windows discovered a corruption in the file %hs. This file has now been repaired.404 /// Windows discovered a corruption in the file %hs. This file has now been repaired.
583 /// Check if any data in the file was lost because of the corruption.405 /// Check if any data in the file was lost because of the corruption.
584 DATA_LOST_REPAIR = 0x80000803,406 DATA_LOST_REPAIR = 0x80000803,
585
586 /// Debugger did not handle the exception.407 /// Debugger did not handle the exception.
587 DBG_EXCEPTION_NOT_HANDLED = 0x80010001,408 DBG_EXCEPTION_NOT_HANDLED = 0x80010001,
588
589 /// The cluster node is already up.409 /// The cluster node is already up.
590 CLUSTER_NODE_ALREADY_UP = 0x80130001,410 CLUSTER_NODE_ALREADY_UP = 0x80130001,
591
592 /// The cluster node is already down.411 /// The cluster node is already down.
593 CLUSTER_NODE_ALREADY_DOWN = 0x80130002,412 CLUSTER_NODE_ALREADY_DOWN = 0x80130002,
594
595 /// The cluster network is already online.413 /// The cluster network is already online.
596 CLUSTER_NETWORK_ALREADY_ONLINE = 0x80130003,414 CLUSTER_NETWORK_ALREADY_ONLINE = 0x80130003,
597
598 /// The cluster network is already offline.415 /// The cluster network is already offline.
599 CLUSTER_NETWORK_ALREADY_OFFLINE = 0x80130004,416 CLUSTER_NETWORK_ALREADY_OFFLINE = 0x80130004,
600
601 /// The cluster node is already a member of the cluster.417 /// The cluster node is already a member of the cluster.
602 CLUSTER_NODE_ALREADY_MEMBER = 0x80130005,418 CLUSTER_NODE_ALREADY_MEMBER = 0x80130005,
603
604 /// The log could not be set to the requested size.419 /// The log could not be set to the requested size.
605 COULD_NOT_RESIZE_LOG = 0x80190009,420 COULD_NOT_RESIZE_LOG = 0x80190009,
606
607 /// There is no transaction metadata on the file.421 /// There is no transaction metadata on the file.
608 NO_TXF_METADATA = 0x80190029,422 NO_TXF_METADATA = 0x80190029,
609
610 /// The file cannot be recovered because there is a handle still open on it.423 /// The file cannot be recovered because there is a handle still open on it.
611 CANT_RECOVER_WITH_HANDLE_OPEN = 0x80190031,424 CANT_RECOVER_WITH_HANDLE_OPEN = 0x80190031,
612
613 /// Transaction metadata is already present on this file and cannot be superseded.425 /// Transaction metadata is already present on this file and cannot be superseded.
614 TXF_METADATA_ALREADY_PRESENT = 0x80190041,426 TXF_METADATA_ALREADY_PRESENT = 0x80190041,
615
616 /// A transaction scope could not be entered because the scope handler has not been initialized.427 /// A transaction scope could not be entered because the scope handler has not been initialized.
617 TRANSACTION_SCOPE_CALLBACKS_NOT_SET = 0x80190042,428 TRANSACTION_SCOPE_CALLBACKS_NOT_SET = 0x80190042,
618
619 /// {Display Driver Stopped Responding and recovered} The %hs display driver has stopped working normally. The recovery had been performed.429 /// {Display Driver Stopped Responding and recovered} The %hs display driver has stopped working normally. The recovery had been performed.
620 VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED = 0x801B00EB,430 VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED = 0x801B00EB,
621
622 /// {Buffer too small} The buffer is too small to contain the entry. No information has been written to the buffer.431 /// {Buffer too small} The buffer is too small to contain the entry. No information has been written to the buffer.
623 FLT_BUFFER_TOO_SMALL = 0x801C0001,432 FLT_BUFFER_TOO_SMALL = 0x801C0001,
624
625 /// Volume metadata read or write is incomplete.433 /// Volume metadata read or write is incomplete.
626 FVE_PARTIAL_METADATA = 0x80210001,434 FVE_PARTIAL_METADATA = 0x80210001,
627
628 /// BitLocker encryption keys were ignored because the volume was in a transient state.435 /// BitLocker encryption keys were ignored because the volume was in a transient state.
629 FVE_TRANSIENT_STATE = 0x80210002,436 FVE_TRANSIENT_STATE = 0x80210002,
630
631 /// {Operation Failed} The requested operation was unsuccessful.437 /// {Operation Failed} The requested operation was unsuccessful.
632 UNSUCCESSFUL = 0xC0000001,438 UNSUCCESSFUL = 0xC0000001,
633
634 /// {Not Implemented} The requested operation is not implemented.439 /// {Not Implemented} The requested operation is not implemented.
635 NOT_IMPLEMENTED = 0xC0000002,440 NOT_IMPLEMENTED = 0xC0000002,
636
637 /// {Invalid Parameter} The specified information class is not a valid information class for the specified object.441 /// {Invalid Parameter} The specified information class is not a valid information class for the specified object.
638 INVALID_INFO_CLASS = 0xC0000003,442 INVALID_INFO_CLASS = 0xC0000003,
639
640 /// The specified information record length does not match the length that is required for the specified information class.443 /// The specified information record length does not match the length that is required for the specified information class.
641 INFO_LENGTH_MISMATCH = 0xC0000004,444 INFO_LENGTH_MISMATCH = 0xC0000004,
642
643 /// The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.445 /// The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.
644 ACCESS_VIOLATION = 0xC0000005,446 ACCESS_VIOLATION = 0xC0000005,
645
646 /// The instruction at 0x%08lx referenced memory at 0x%08lx.447 /// The instruction at 0x%08lx referenced memory at 0x%08lx.
647 /// The required data was not placed into memory because of an I/O error status of 0x%08lx.448 /// The required data was not placed into memory because of an I/O error status of 0x%08lx.
648 IN_PAGE_ERROR = 0xC0000006,449 IN_PAGE_ERROR = 0xC0000006,
649
650 /// The page file quota for the process has been exhausted.450 /// The page file quota for the process has been exhausted.
651 PAGEFILE_QUOTA = 0xC0000007,451 PAGEFILE_QUOTA = 0xC0000007,
652
653 /// An invalid HANDLE was specified.452 /// An invalid HANDLE was specified.
654 INVALID_HANDLE = 0xC0000008,453 INVALID_HANDLE = 0xC0000008,
655
656 /// An invalid initial stack was specified in a call to NtCreateThread.454 /// An invalid initial stack was specified in a call to NtCreateThread.
657 BAD_INITIAL_STACK = 0xC0000009,455 BAD_INITIAL_STACK = 0xC0000009,
658
659 /// An invalid initial start address was specified in a call to NtCreateThread.456 /// An invalid initial start address was specified in a call to NtCreateThread.
660 BAD_INITIAL_PC = 0xC000000A,457 BAD_INITIAL_PC = 0xC000000A,
661
662 /// An invalid client ID was specified.458 /// An invalid client ID was specified.
663 INVALID_CID = 0xC000000B,459 INVALID_CID = 0xC000000B,
664
665 /// An attempt was made to cancel or set a timer that has an associated APC and the specified thread is not the thread that originally set the timer with an associated APC routine.460 /// An attempt was made to cancel or set a timer that has an associated APC and the specified thread is not the thread that originally set the timer with an associated APC routine.
666 TIMER_NOT_CANCELED = 0xC000000C,461 TIMER_NOT_CANCELED = 0xC000000C,
667
668 /// An invalid parameter was passed to a service or function.462 /// An invalid parameter was passed to a service or function.
669 INVALID_PARAMETER = 0xC000000D,463 INVALID_PARAMETER = 0xC000000D,
670
671 /// A device that does not exist was specified.464 /// A device that does not exist was specified.
672 NO_SUCH_DEVICE = 0xC000000E,465 NO_SUCH_DEVICE = 0xC000000E,
673
674 /// {File Not Found} The file %hs does not exist.466 /// {File Not Found} The file %hs does not exist.
675 NO_SUCH_FILE = 0xC000000F,467 NO_SUCH_FILE = 0xC000000F,
676
677 /// The specified request is not a valid operation for the target device.468 /// The specified request is not a valid operation for the target device.
678 INVALID_DEVICE_REQUEST = 0xC0000010,469 INVALID_DEVICE_REQUEST = 0xC0000010,
679
680 /// The end-of-file marker has been reached.470 /// The end-of-file marker has been reached.
681 /// There is no valid data in the file beyond this marker.471 /// There is no valid data in the file beyond this marker.
682 END_OF_FILE = 0xC0000011,472 END_OF_FILE = 0xC0000011,
683
684 /// {Wrong Volume} The wrong volume is in the drive. Insert volume %hs into drive %hs.473 /// {Wrong Volume} The wrong volume is in the drive. Insert volume %hs into drive %hs.
685 WRONG_VOLUME = 0xC0000012,474 WRONG_VOLUME = 0xC0000012,
686
687 /// {No Disk} There is no disk in the drive. Insert a disk into drive %hs.475 /// {No Disk} There is no disk in the drive. Insert a disk into drive %hs.
688 NO_MEDIA_IN_DEVICE = 0xC0000013,476 NO_MEDIA_IN_DEVICE = 0xC0000013,
689
690 /// {Unknown Disk Format} The disk in drive %hs is not formatted properly.477 /// {Unknown Disk Format} The disk in drive %hs is not formatted properly.
691 /// Check the disk, and reformat it, if needed.478 /// Check the disk, and reformat it, if needed.
692 UNRECOGNIZED_MEDIA = 0xC0000014,479 UNRECOGNIZED_MEDIA = 0xC0000014,
693
694 /// {Sector Not Found} The specified sector does not exist.480 /// {Sector Not Found} The specified sector does not exist.
695 NONEXISTENT_SECTOR = 0xC0000015,481 NONEXISTENT_SECTOR = 0xC0000015,
696
697 /// {Still Busy} The specified I/O request packet (IRP) cannot be disposed of because the I/O operation is not complete.482 /// {Still Busy} The specified I/O request packet (IRP) cannot be disposed of because the I/O operation is not complete.
698 MORE_PROCESSING_REQUIRED = 0xC0000016,483 MORE_PROCESSING_REQUIRED = 0xC0000016,
699
700 /// {Not Enough Quota} Not enough virtual memory or paging file quota is available to complete the specified operation.484 /// {Not Enough Quota} Not enough virtual memory or paging file quota is available to complete the specified operation.
701 NO_MEMORY = 0xC0000017,485 NO_MEMORY = 0xC0000017,
702
703 /// {Conflicting Address Range} The specified address range conflicts with the address space.486 /// {Conflicting Address Range} The specified address range conflicts with the address space.
704 CONFLICTING_ADDRESSES = 0xC0000018,487 CONFLICTING_ADDRESSES = 0xC0000018,
705
706 /// The address range to unmap is not a mapped view.488 /// The address range to unmap is not a mapped view.
707 NOT_MAPPED_VIEW = 0xC0000019,489 NOT_MAPPED_VIEW = 0xC0000019,
708
709 /// The virtual memory cannot be freed.490 /// The virtual memory cannot be freed.
710 UNABLE_TO_FREE_VM = 0xC000001A,491 UNABLE_TO_FREE_VM = 0xC000001A,
711
712 /// The specified section cannot be deleted.492 /// The specified section cannot be deleted.
713 UNABLE_TO_DELETE_SECTION = 0xC000001B,493 UNABLE_TO_DELETE_SECTION = 0xC000001B,
714
715 /// An invalid system service was specified in a system service call.494 /// An invalid system service was specified in a system service call.
716 INVALID_SYSTEM_SERVICE = 0xC000001C,495 INVALID_SYSTEM_SERVICE = 0xC000001C,
717
718 /// {EXCEPTION} Illegal Instruction An attempt was made to execute an illegal instruction.496 /// {EXCEPTION} Illegal Instruction An attempt was made to execute an illegal instruction.
719 ILLEGAL_INSTRUCTION = 0xC000001D,497 ILLEGAL_INSTRUCTION = 0xC000001D,
720
721 /// {Invalid Lock Sequence} An attempt was made to execute an invalid lock sequence.498 /// {Invalid Lock Sequence} An attempt was made to execute an invalid lock sequence.
722 INVALID_LOCK_SEQUENCE = 0xC000001E,499 INVALID_LOCK_SEQUENCE = 0xC000001E,
723
724 /// {Invalid Mapping} An attempt was made to create a view for a section that is bigger than the section.500 /// {Invalid Mapping} An attempt was made to create a view for a section that is bigger than the section.
725 INVALID_VIEW_SIZE = 0xC000001F,501 INVALID_VIEW_SIZE = 0xC000001F,
726
727 /// {Bad File} The attributes of the specified mapping file for a section of memory cannot be read.502 /// {Bad File} The attributes of the specified mapping file for a section of memory cannot be read.
728 INVALID_FILE_FOR_SECTION = 0xC0000020,503 INVALID_FILE_FOR_SECTION = 0xC0000020,
729
730 /// {Already Committed} The specified address range is already committed.504 /// {Already Committed} The specified address range is already committed.
731 ALREADY_COMMITTED = 0xC0000021,505 ALREADY_COMMITTED = 0xC0000021,
732
733 /// {Access Denied} A process has requested access to an object but has not been granted those access rights.506 /// {Access Denied} A process has requested access to an object but has not been granted those access rights.
734 ACCESS_DENIED = 0xC0000022,507 ACCESS_DENIED = 0xC0000022,
735
736 /// {Buffer Too Small} The buffer is too small to contain the entry. No information has been written to the buffer.508 /// {Buffer Too Small} The buffer is too small to contain the entry. No information has been written to the buffer.
737 BUFFER_TOO_SMALL = 0xC0000023,509 BUFFER_TOO_SMALL = 0xC0000023,
738
739 /// {Wrong Type} There is a mismatch between the type of object that is required by the requested operation and the type of object that is specified in the request.510 /// {Wrong Type} There is a mismatch between the type of object that is required by the requested operation and the type of object that is specified in the request.
740 OBJECT_TYPE_MISMATCH = 0xC0000024,511 OBJECT_TYPE_MISMATCH = 0xC0000024,
741
742 /// {EXCEPTION} Cannot Continue Windows cannot continue from this exception.512 /// {EXCEPTION} Cannot Continue Windows cannot continue from this exception.
743 NONCONTINUABLE_EXCEPTION = 0xC0000025,513 NONCONTINUABLE_EXCEPTION = 0xC0000025,
744
745 /// An invalid exception disposition was returned by an exception handler.514 /// An invalid exception disposition was returned by an exception handler.
746 INVALID_DISPOSITION = 0xC0000026,515 INVALID_DISPOSITION = 0xC0000026,
747
748 /// Unwind exception code.516 /// Unwind exception code.
749 UNWIND = 0xC0000027,517 UNWIND = 0xC0000027,
750
751 /// An invalid or unaligned stack was encountered during an unwind operation.518 /// An invalid or unaligned stack was encountered during an unwind operation.
752 BAD_STACK = 0xC0000028,519 BAD_STACK = 0xC0000028,
753
754 /// An invalid unwind target was encountered during an unwind operation.520 /// An invalid unwind target was encountered during an unwind operation.
755 INVALID_UNWIND_TARGET = 0xC0000029,521 INVALID_UNWIND_TARGET = 0xC0000029,
756
757 /// An attempt was made to unlock a page of memory that was not locked.522 /// An attempt was made to unlock a page of memory that was not locked.
758 NOT_LOCKED = 0xC000002A,523 NOT_LOCKED = 0xC000002A,
759
760 /// A device parity error on an I/O operation.524 /// A device parity error on an I/O operation.
761 PARITY_ERROR = 0xC000002B,525 PARITY_ERROR = 0xC000002B,
762
763 /// An attempt was made to decommit uncommitted virtual memory.526 /// An attempt was made to decommit uncommitted virtual memory.
764 UNABLE_TO_DECOMMIT_VM = 0xC000002C,527 UNABLE_TO_DECOMMIT_VM = 0xC000002C,
765
766 /// An attempt was made to change the attributes on memory that has not been committed.528 /// An attempt was made to change the attributes on memory that has not been committed.
767 NOT_COMMITTED = 0xC000002D,529 NOT_COMMITTED = 0xC000002D,
768
769 /// Invalid object attributes specified to NtCreatePort or invalid port attributes specified to NtConnectPort.530 /// Invalid object attributes specified to NtCreatePort or invalid port attributes specified to NtConnectPort.
770 INVALID_PORT_ATTRIBUTES = 0xC000002E,531 INVALID_PORT_ATTRIBUTES = 0xC000002E,
771
772 /// The length of the message that was passed to NtRequestPort or NtRequestWaitReplyPort is longer than the maximum message that is allowed by the port.532 /// The length of the message that was passed to NtRequestPort or NtRequestWaitReplyPort is longer than the maximum message that is allowed by the port.
773 PORT_MESSAGE_TOO_LONG = 0xC000002F,533 PORT_MESSAGE_TOO_LONG = 0xC000002F,
774
775 /// An invalid combination of parameters was specified.534 /// An invalid combination of parameters was specified.
776 INVALID_PARAMETER_MIX = 0xC0000030,535 INVALID_PARAMETER_MIX = 0xC0000030,
777
778 /// An attempt was made to lower a quota limit below the current usage.536 /// An attempt was made to lower a quota limit below the current usage.
779 INVALID_QUOTA_LOWER = 0xC0000031,537 INVALID_QUOTA_LOWER = 0xC0000031,
780
781 /// {Corrupt Disk} The file system structure on the disk is corrupt and unusable. Run the Chkdsk utility on the volume %hs.538 /// {Corrupt Disk} The file system structure on the disk is corrupt and unusable. Run the Chkdsk utility on the volume %hs.
782 DISK_CORRUPT_ERROR = 0xC0000032,539 DISK_CORRUPT_ERROR = 0xC0000032,
783
784 /// The object name is invalid.540 /// The object name is invalid.
785 OBJECT_NAME_INVALID = 0xC0000033,541 OBJECT_NAME_INVALID = 0xC0000033,
786
787 /// The object name is not found.542 /// The object name is not found.
788 OBJECT_NAME_NOT_FOUND = 0xC0000034,543 OBJECT_NAME_NOT_FOUND = 0xC0000034,
789
790 /// The object name already exists.544 /// The object name already exists.
791 OBJECT_NAME_COLLISION = 0xC0000035,545 OBJECT_NAME_COLLISION = 0xC0000035,
792
793 /// An attempt was made to send a message to a disconnected communication port.546 /// An attempt was made to send a message to a disconnected communication port.
794 PORT_DISCONNECTED = 0xC0000037,547 PORT_DISCONNECTED = 0xC0000037,
795
796 /// An attempt was made to attach to a device that was already attached to another device.548 /// An attempt was made to attach to a device that was already attached to another device.
797 DEVICE_ALREADY_ATTACHED = 0xC0000038,549 DEVICE_ALREADY_ATTACHED = 0xC0000038,
798
799 /// The object path component was not a directory object.550 /// The object path component was not a directory object.
800 OBJECT_PATH_INVALID = 0xC0000039,551 OBJECT_PATH_INVALID = 0xC0000039,
801
802 /// {Path Not Found} The path %hs does not exist.552 /// {Path Not Found} The path %hs does not exist.
803 OBJECT_PATH_NOT_FOUND = 0xC000003A,553 OBJECT_PATH_NOT_FOUND = 0xC000003A,
804
805 /// The object path component was not a directory object.554 /// The object path component was not a directory object.
806 OBJECT_PATH_SYNTAX_BAD = 0xC000003B,555 OBJECT_PATH_SYNTAX_BAD = 0xC000003B,
807
808 /// {Data Overrun} A data overrun error occurred.556 /// {Data Overrun} A data overrun error occurred.
809 DATA_OVERRUN = 0xC000003C,557 DATA_OVERRUN = 0xC000003C,
810
811 /// {Data Late} A data late error occurred.558 /// {Data Late} A data late error occurred.
812 DATA_LATE_ERROR = 0xC000003D,559 DATA_LATE_ERROR = 0xC000003D,
813
814 /// {Data Error} An error occurred in reading or writing data.560 /// {Data Error} An error occurred in reading or writing data.
815 DATA_ERROR = 0xC000003E,561 DATA_ERROR = 0xC000003E,
816
817 /// {Bad CRC} A cyclic redundancy check (CRC) checksum error occurred.562 /// {Bad CRC} A cyclic redundancy check (CRC) checksum error occurred.
818 CRC_ERROR = 0xC000003F,563 CRC_ERROR = 0xC000003F,
819
820 /// {Section Too Large} The specified section is too big to map the file.564 /// {Section Too Large} The specified section is too big to map the file.
821 SECTION_TOO_BIG = 0xC0000040,565 SECTION_TOO_BIG = 0xC0000040,
822
823 /// The NtConnectPort request is refused.566 /// The NtConnectPort request is refused.
824 PORT_CONNECTION_REFUSED = 0xC0000041,567 PORT_CONNECTION_REFUSED = 0xC0000041,
825
826 /// The type of port handle is invalid for the operation that is requested.568 /// The type of port handle is invalid for the operation that is requested.
827 INVALID_PORT_HANDLE = 0xC0000042,569 INVALID_PORT_HANDLE = 0xC0000042,
828
829 /// A file cannot be opened because the share access flags are incompatible.570 /// A file cannot be opened because the share access flags are incompatible.
830 SHARING_VIOLATION = 0xC0000043,571 SHARING_VIOLATION = 0xC0000043,
831
832 /// Insufficient quota exists to complete the operation.572 /// Insufficient quota exists to complete the operation.
833 QUOTA_EXCEEDED = 0xC0000044,573 QUOTA_EXCEEDED = 0xC0000044,
834
835 /// The specified page protection was not valid.574 /// The specified page protection was not valid.
836 INVALID_PAGE_PROTECTION = 0xC0000045,575 INVALID_PAGE_PROTECTION = 0xC0000045,
837
838 /// An attempt to release a mutant object was made by a thread that was not the owner of the mutant object.576 /// An attempt to release a mutant object was made by a thread that was not the owner of the mutant object.
839 MUTANT_NOT_OWNED = 0xC0000046,577 MUTANT_NOT_OWNED = 0xC0000046,
840
841 /// An attempt was made to release a semaphore such that its maximum count would have been exceeded.578 /// An attempt was made to release a semaphore such that its maximum count would have been exceeded.
842 SEMAPHORE_LIMIT_EXCEEDED = 0xC0000047,579 SEMAPHORE_LIMIT_EXCEEDED = 0xC0000047,
843
844 /// An attempt was made to set the DebugPort or ExceptionPort of a process, but a port already exists in the process, or an attempt was made to set the CompletionPort of a file but a port was already set in the file, or an attempt was made to set the associated completion port of an ALPC port but it is already set.580 /// An attempt was made to set the DebugPort or ExceptionPort of a process, but a port already exists in the process, or an attempt was made to set the CompletionPort of a file but a port was already set in the file, or an attempt was made to set the associated completion port of an ALPC port but it is already set.
845 PORT_ALREADY_SET = 0xC0000048,581 PORT_ALREADY_SET = 0xC0000048,
846
847 /// An attempt was made to query image information on a section that does not map an image.582 /// An attempt was made to query image information on a section that does not map an image.
848 SECTION_NOT_IMAGE = 0xC0000049,583 SECTION_NOT_IMAGE = 0xC0000049,
849
850 /// An attempt was made to suspend a thread whose suspend count was at its maximum.584 /// An attempt was made to suspend a thread whose suspend count was at its maximum.
851 SUSPEND_COUNT_EXCEEDED = 0xC000004A,585 SUSPEND_COUNT_EXCEEDED = 0xC000004A,
852
853 /// An attempt was made to suspend a thread that has begun termination.586 /// An attempt was made to suspend a thread that has begun termination.
854 THREAD_IS_TERMINATING = 0xC000004B,587 THREAD_IS_TERMINATING = 0xC000004B,
855
856 /// An attempt was made to set the working set limit to an invalid value (for example, the minimum greater than maximum).588 /// An attempt was made to set the working set limit to an invalid value (for example, the minimum greater than maximum).
857 BAD_WORKING_SET_LIMIT = 0xC000004C,589 BAD_WORKING_SET_LIMIT = 0xC000004C,
858
859 /// A section was created to map a file that is not compatible with an already existing section that maps the same file.590 /// A section was created to map a file that is not compatible with an already existing section that maps the same file.
860 INCOMPATIBLE_FILE_MAP = 0xC000004D,591 INCOMPATIBLE_FILE_MAP = 0xC000004D,
861
862 /// A view to a section specifies a protection that is incompatible with the protection of the initial view.592 /// A view to a section specifies a protection that is incompatible with the protection of the initial view.
863 SECTION_PROTECTION = 0xC000004E,593 SECTION_PROTECTION = 0xC000004E,
864
865 /// An operation involving EAs failed because the file system does not support EAs.594 /// An operation involving EAs failed because the file system does not support EAs.
866 EAS_NOT_SUPPORTED = 0xC000004F,595 EAS_NOT_SUPPORTED = 0xC000004F,
867
868 /// An EA operation failed because the EA set is too large.596 /// An EA operation failed because the EA set is too large.
869 EA_TOO_LARGE = 0xC0000050,597 EA_TOO_LARGE = 0xC0000050,
870
871 /// An EA operation failed because the name or EA index is invalid.598 /// An EA operation failed because the name or EA index is invalid.
872 NONEXISTENT_EA_ENTRY = 0xC0000051,599 NONEXISTENT_EA_ENTRY = 0xC0000051,
873
874 /// The file for which EAs were requested has no EAs.600 /// The file for which EAs were requested has no EAs.
875 NO_EAS_ON_FILE = 0xC0000052,601 NO_EAS_ON_FILE = 0xC0000052,
876
877 /// The EA is corrupt and cannot be read.602 /// The EA is corrupt and cannot be read.
878 EA_CORRUPT_ERROR = 0xC0000053,603 EA_CORRUPT_ERROR = 0xC0000053,
879
880 /// A requested read/write cannot be granted due to a conflicting file lock.604 /// A requested read/write cannot be granted due to a conflicting file lock.
881 FILE_LOCK_CONFLICT = 0xC0000054,605 FILE_LOCK_CONFLICT = 0xC0000054,
882
883 /// A requested file lock cannot be granted due to other existing locks.606 /// A requested file lock cannot be granted due to other existing locks.
884 LOCK_NOT_GRANTED = 0xC0000055,607 LOCK_NOT_GRANTED = 0xC0000055,
885
886 /// A non-close operation has been requested of a file object that has a delete pending.608 /// A non-close operation has been requested of a file object that has a delete pending.
887 DELETE_PENDING = 0xC0000056,609 DELETE_PENDING = 0xC0000056,
888
889 /// An attempt was made to set the control attribute on a file.610 /// An attempt was made to set the control attribute on a file.
890 /// This attribute is not supported in the destination file system.611 /// This attribute is not supported in the destination file system.
891 CTL_FILE_NOT_SUPPORTED = 0xC0000057,612 CTL_FILE_NOT_SUPPORTED = 0xC0000057,
892
893 /// Indicates a revision number that was encountered or specified is not one that is known by the service.613 /// Indicates a revision number that was encountered or specified is not one that is known by the service.
894 /// It might be a more recent revision than the service is aware of.614 /// It might be a more recent revision than the service is aware of.
895 UNKNOWN_REVISION = 0xC0000058,615 UNKNOWN_REVISION = 0xC0000058,
896
897 /// Indicates that two revision levels are incompatible.616 /// Indicates that two revision levels are incompatible.
898 REVISION_MISMATCH = 0xC0000059,617 REVISION_MISMATCH = 0xC0000059,
899
900 /// Indicates a particular security ID cannot be assigned as the owner of an object.618 /// Indicates a particular security ID cannot be assigned as the owner of an object.
901 INVALID_OWNER = 0xC000005A,619 INVALID_OWNER = 0xC000005A,
902
903 /// Indicates a particular security ID cannot be assigned as the primary group of an object.620 /// Indicates a particular security ID cannot be assigned as the primary group of an object.
904 INVALID_PRIMARY_GROUP = 0xC000005B,621 INVALID_PRIMARY_GROUP = 0xC000005B,
905
906 /// An attempt has been made to operate on an impersonation token by a thread that is not currently impersonating a client.622 /// An attempt has been made to operate on an impersonation token by a thread that is not currently impersonating a client.
907 NO_IMPERSONATION_TOKEN = 0xC000005C,623 NO_IMPERSONATION_TOKEN = 0xC000005C,
908
909 /// A mandatory group cannot be disabled.624 /// A mandatory group cannot be disabled.
910 CANT_DISABLE_MANDATORY = 0xC000005D,625 CANT_DISABLE_MANDATORY = 0xC000005D,
911
912 /// No logon servers are currently available to service the logon request.626 /// No logon servers are currently available to service the logon request.
913 NO_LOGON_SERVERS = 0xC000005E,627 NO_LOGON_SERVERS = 0xC000005E,
914
915 /// A specified logon session does not exist. It might already have been terminated.628 /// A specified logon session does not exist. It might already have been terminated.
916 NO_SUCH_LOGON_SESSION = 0xC000005F,629 NO_SUCH_LOGON_SESSION = 0xC000005F,
917
918 /// A specified privilege does not exist.630 /// A specified privilege does not exist.
919 NO_SUCH_PRIVILEGE = 0xC0000060,631 NO_SUCH_PRIVILEGE = 0xC0000060,
920
921 /// A required privilege is not held by the client.632 /// A required privilege is not held by the client.
922 PRIVILEGE_NOT_HELD = 0xC0000061,633 PRIVILEGE_NOT_HELD = 0xC0000061,
923
924 /// The name provided is not a properly formed account name.634 /// The name provided is not a properly formed account name.
925 INVALID_ACCOUNT_NAME = 0xC0000062,635 INVALID_ACCOUNT_NAME = 0xC0000062,
926
927 /// The specified account already exists.636 /// The specified account already exists.
928 USER_EXISTS = 0xC0000063,637 USER_EXISTS = 0xC0000063,
929
930 /// The specified account does not exist.638 /// The specified account does not exist.
931 NO_SUCH_USER = 0xC0000064,639 NO_SUCH_USER = 0xC0000064,
932
933 /// The specified group already exists.640 /// The specified group already exists.
934 GROUP_EXISTS = 0xC0000065,641 GROUP_EXISTS = 0xC0000065,
935
936 /// The specified group does not exist.642 /// The specified group does not exist.
937 NO_SUCH_GROUP = 0xC0000066,643 NO_SUCH_GROUP = 0xC0000066,
938
939 /// The specified user account is already in the specified group account.644 /// The specified user account is already in the specified group account.
940 /// Also used to indicate a group cannot be deleted because it contains a member.645 /// Also used to indicate a group cannot be deleted because it contains a member.
941 MEMBER_IN_GROUP = 0xC0000067,646 MEMBER_IN_GROUP = 0xC0000067,
942
943 /// The specified user account is not a member of the specified group account.647 /// The specified user account is not a member of the specified group account.
944 MEMBER_NOT_IN_GROUP = 0xC0000068,648 MEMBER_NOT_IN_GROUP = 0xC0000068,
945
946 /// Indicates the requested operation would disable or delete the last remaining administration account.649 /// Indicates the requested operation would disable or delete the last remaining administration account.
947 /// This is not allowed to prevent creating a situation in which the system cannot be administrated.650 /// This is not allowed to prevent creating a situation in which the system cannot be administrated.
948 LAST_ADMIN = 0xC0000069,651 LAST_ADMIN = 0xC0000069,
949
950 /// When trying to update a password, this return status indicates that the value provided as the current password is not correct.652 /// When trying to update a password, this return status indicates that the value provided as the current password is not correct.
951 WRONG_PASSWORD = 0xC000006A,653 WRONG_PASSWORD = 0xC000006A,
952
953 /// When trying to update a password, this return status indicates that the value provided for the new password contains values that are not allowed in passwords.654 /// When trying to update a password, this return status indicates that the value provided for the new password contains values that are not allowed in passwords.
954 ILL_FORMED_PASSWORD = 0xC000006B,655 ILL_FORMED_PASSWORD = 0xC000006B,
955
956 /// When trying to update a password, this status indicates that some password update rule has been violated.656 /// When trying to update a password, this status indicates that some password update rule has been violated.
957 /// For example, the password might not meet length criteria.657 /// For example, the password might not meet length criteria.
958 PASSWORD_RESTRICTION = 0xC000006C,658 PASSWORD_RESTRICTION = 0xC000006C,
959
960 /// The attempted logon is invalid.659 /// The attempted logon is invalid.
961 /// This is either due to a bad username or authentication information.660 /// This is either due to a bad username or authentication information.
962 LOGON_FAILURE = 0xC000006D,661 LOGON_FAILURE = 0xC000006D,
963
964 /// Indicates a referenced user name and authentication information are valid, but some user account restriction has prevented successful authentication (such as time-of-day restrictions).662 /// Indicates a referenced user name and authentication information are valid, but some user account restriction has prevented successful authentication (such as time-of-day restrictions).
965 ACCOUNT_RESTRICTION = 0xC000006E,663 ACCOUNT_RESTRICTION = 0xC000006E,
966
967 /// The user account has time restrictions and cannot be logged onto at this time.664 /// The user account has time restrictions and cannot be logged onto at this time.
968 INVALID_LOGON_HOURS = 0xC000006F,665 INVALID_LOGON_HOURS = 0xC000006F,
969
970 /// The user account is restricted so that it cannot be used to log on from the source workstation.666 /// The user account is restricted so that it cannot be used to log on from the source workstation.
971 INVALID_WORKSTATION = 0xC0000070,667 INVALID_WORKSTATION = 0xC0000070,
972
973 /// The user account password has expired.668 /// The user account password has expired.
974 PASSWORD_EXPIRED = 0xC0000071,669 PASSWORD_EXPIRED = 0xC0000071,
975
976 /// The referenced account is currently disabled and cannot be logged on to.670 /// The referenced account is currently disabled and cannot be logged on to.
977 ACCOUNT_DISABLED = 0xC0000072,671 ACCOUNT_DISABLED = 0xC0000072,
978
979 /// None of the information to be translated has been translated.672 /// None of the information to be translated has been translated.
980 NONE_MAPPED = 0xC0000073,673 NONE_MAPPED = 0xC0000073,
981
982 /// The number of LUIDs requested cannot be allocated with a single allocation.674 /// The number of LUIDs requested cannot be allocated with a single allocation.
983 TOO_MANY_LUIDS_REQUESTED = 0xC0000074,675 TOO_MANY_LUIDS_REQUESTED = 0xC0000074,
984
985 /// Indicates there are no more LUIDs to allocate.676 /// Indicates there are no more LUIDs to allocate.
986 LUIDS_EXHAUSTED = 0xC0000075,677 LUIDS_EXHAUSTED = 0xC0000075,
987
988 /// Indicates the sub-authority value is invalid for the particular use.678 /// Indicates the sub-authority value is invalid for the particular use.
989 INVALID_SUB_AUTHORITY = 0xC0000076,679 INVALID_SUB_AUTHORITY = 0xC0000076,
990
991 /// Indicates the ACL structure is not valid.680 /// Indicates the ACL structure is not valid.
992 INVALID_ACL = 0xC0000077,681 INVALID_ACL = 0xC0000077,
993
994 /// Indicates the SID structure is not valid.682 /// Indicates the SID structure is not valid.
995 INVALID_SID = 0xC0000078,683 INVALID_SID = 0xC0000078,
996
997 /// Indicates the SECURITY_DESCRIPTOR structure is not valid.684 /// Indicates the SECURITY_DESCRIPTOR structure is not valid.
998 INVALID_SECURITY_DESCR = 0xC0000079,685 INVALID_SECURITY_DESCR = 0xC0000079,
999
1000 /// Indicates the specified procedure address cannot be found in the DLL.686 /// Indicates the specified procedure address cannot be found in the DLL.
1001 PROCEDURE_NOT_FOUND = 0xC000007A,687 PROCEDURE_NOT_FOUND = 0xC000007A,
1002
1003 /// {Bad Image} %hs is either not designed to run on Windows or it contains an error.688 /// {Bad Image} %hs is either not designed to run on Windows or it contains an error.
1004 /// Try installing the program again using the original installation media or contact your system administrator or the software vendor for support.689 /// Try installing the program again using the original installation media or contact your system administrator or the software vendor for support.
1005 INVALID_IMAGE_FORMAT = 0xC000007B,690 INVALID_IMAGE_FORMAT = 0xC000007B,
1006
1007 /// An attempt was made to reference a token that does not exist.691 /// An attempt was made to reference a token that does not exist.
1008 /// This is typically done by referencing the token that is associated with a thread when the thread is not impersonating a client.692 /// This is typically done by referencing the token that is associated with a thread when the thread is not impersonating a client.
1009 NO_TOKEN = 0xC000007C,693 NO_TOKEN = 0xC000007C,
1010
1011 /// Indicates that an attempt to build either an inherited ACL or ACE was not successful. This can be caused by a number of things.694 /// Indicates that an attempt to build either an inherited ACL or ACE was not successful. This can be caused by a number of things.
1012 /// One of the more probable causes is the replacement of a CreatorId with a SID that did not fit into the ACE or ACL.695 /// One of the more probable causes is the replacement of a CreatorId with a SID that did not fit into the ACE or ACL.
1013 BAD_INHERITANCE_ACL = 0xC000007D,696 BAD_INHERITANCE_ACL = 0xC000007D,
1014
1015 /// The range specified in NtUnlockFile was not locked.697 /// The range specified in NtUnlockFile was not locked.
1016 RANGE_NOT_LOCKED = 0xC000007E,698 RANGE_NOT_LOCKED = 0xC000007E,
1017
1018 /// An operation failed because the disk was full.699 /// An operation failed because the disk was full.
1019 DISK_FULL = 0xC000007F,700 DISK_FULL = 0xC000007F,
1020
1021 /// The GUID allocation server is disabled at the moment.701 /// The GUID allocation server is disabled at the moment.
1022 SERVER_DISABLED = 0xC0000080,702 SERVER_DISABLED = 0xC0000080,
1023
1024 /// The GUID allocation server is enabled at the moment.703 /// The GUID allocation server is enabled at the moment.
1025 SERVER_NOT_DISABLED = 0xC0000081,704 SERVER_NOT_DISABLED = 0xC0000081,
1026
1027 /// Too many GUIDs were requested from the allocation server at once.705 /// Too many GUIDs were requested from the allocation server at once.
1028 TOO_MANY_GUIDS_REQUESTED = 0xC0000082,706 TOO_MANY_GUIDS_REQUESTED = 0xC0000082,
1029
1030 /// The GUIDs could not be allocated because the Authority Agent was exhausted.707 /// The GUIDs could not be allocated because the Authority Agent was exhausted.
1031 GUIDS_EXHAUSTED = 0xC0000083,708 GUIDS_EXHAUSTED = 0xC0000083,
1032
1033 /// The value provided was an invalid value for an identifier authority.709 /// The value provided was an invalid value for an identifier authority.
1034 INVALID_ID_AUTHORITY = 0xC0000084,710 INVALID_ID_AUTHORITY = 0xC0000084,
1035
1036 /// No more authority agent values are available for the particular identifier authority value.711 /// No more authority agent values are available for the particular identifier authority value.
1037 AGENTS_EXHAUSTED = 0xC0000085,712 AGENTS_EXHAUSTED = 0xC0000085,
1038
1039 /// An invalid volume label has been specified.713 /// An invalid volume label has been specified.
1040 INVALID_VOLUME_LABEL = 0xC0000086,714 INVALID_VOLUME_LABEL = 0xC0000086,
1041
1042 /// A mapped section could not be extended.715 /// A mapped section could not be extended.
1043 SECTION_NOT_EXTENDED = 0xC0000087,716 SECTION_NOT_EXTENDED = 0xC0000087,
1044
1045 /// Specified section to flush does not map a data file.717 /// Specified section to flush does not map a data file.
1046 NOT_MAPPED_DATA = 0xC0000088,718 NOT_MAPPED_DATA = 0xC0000088,
1047
1048 /// Indicates the specified image file did not contain a resource section.719 /// Indicates the specified image file did not contain a resource section.
1049 RESOURCE_DATA_NOT_FOUND = 0xC0000089,720 RESOURCE_DATA_NOT_FOUND = 0xC0000089,
1050
1051 /// Indicates the specified resource type cannot be found in the image file.721 /// Indicates the specified resource type cannot be found in the image file.
1052 RESOURCE_TYPE_NOT_FOUND = 0xC000008A,722 RESOURCE_TYPE_NOT_FOUND = 0xC000008A,
1053
1054 /// Indicates the specified resource name cannot be found in the image file.723 /// Indicates the specified resource name cannot be found in the image file.
1055 RESOURCE_NAME_NOT_FOUND = 0xC000008B,724 RESOURCE_NAME_NOT_FOUND = 0xC000008B,
1056
1057 /// {EXCEPTION} Array bounds exceeded.725 /// {EXCEPTION} Array bounds exceeded.
1058 ARRAY_BOUNDS_EXCEEDED = 0xC000008C,726 ARRAY_BOUNDS_EXCEEDED = 0xC000008C,
1059
1060 /// {EXCEPTION} Floating-point denormal operand.727 /// {EXCEPTION} Floating-point denormal operand.
1061 FLOAT_DENORMAL_OPERAND = 0xC000008D,728 FLOAT_DENORMAL_OPERAND = 0xC000008D,
1062
1063 /// {EXCEPTION} Floating-point division by zero.729 /// {EXCEPTION} Floating-point division by zero.
1064 FLOAT_DIVIDE_BY_ZERO = 0xC000008E,730 FLOAT_DIVIDE_BY_ZERO = 0xC000008E,
1065
1066 /// {EXCEPTION} Floating-point inexact result.731 /// {EXCEPTION} Floating-point inexact result.
1067 FLOAT_INEXACT_RESULT = 0xC000008F,732 FLOAT_INEXACT_RESULT = 0xC000008F,
1068
1069 /// {EXCEPTION} Floating-point invalid operation.733 /// {EXCEPTION} Floating-point invalid operation.
1070 FLOAT_INVALID_OPERATION = 0xC0000090,734 FLOAT_INVALID_OPERATION = 0xC0000090,
1071
1072 /// {EXCEPTION} Floating-point overflow.735 /// {EXCEPTION} Floating-point overflow.
1073 FLOAT_OVERFLOW = 0xC0000091,736 FLOAT_OVERFLOW = 0xC0000091,
1074
1075 /// {EXCEPTION} Floating-point stack check.737 /// {EXCEPTION} Floating-point stack check.
1076 FLOAT_STACK_CHECK = 0xC0000092,738 FLOAT_STACK_CHECK = 0xC0000092,
1077
1078 /// {EXCEPTION} Floating-point underflow.739 /// {EXCEPTION} Floating-point underflow.
1079 FLOAT_UNDERFLOW = 0xC0000093,740 FLOAT_UNDERFLOW = 0xC0000093,
1080
1081 /// {EXCEPTION} Integer division by zero.741 /// {EXCEPTION} Integer division by zero.
1082 INTEGER_DIVIDE_BY_ZERO = 0xC0000094,742 INTEGER_DIVIDE_BY_ZERO = 0xC0000094,
1083
1084 /// {EXCEPTION} Integer overflow.743 /// {EXCEPTION} Integer overflow.
1085 INTEGER_OVERFLOW = 0xC0000095,744 INTEGER_OVERFLOW = 0xC0000095,
1086
1087 /// {EXCEPTION} Privileged instruction.745 /// {EXCEPTION} Privileged instruction.
1088 PRIVILEGED_INSTRUCTION = 0xC0000096,746 PRIVILEGED_INSTRUCTION = 0xC0000096,
1089
1090 /// An attempt was made to install more paging files than the system supports.747 /// An attempt was made to install more paging files than the system supports.
1091 TOO_MANY_PAGING_FILES = 0xC0000097,748 TOO_MANY_PAGING_FILES = 0xC0000097,
1092
1093 /// The volume for a file has been externally altered such that the opened file is no longer valid.749 /// The volume for a file has been externally altered such that the opened file is no longer valid.
1094 FILE_INVALID = 0xC0000098,750 FILE_INVALID = 0xC0000098,
1095
1096 /// When a block of memory is allotted for future updates, such as the memory allocated to hold discretionary access control and primary group information, successive updates might exceed the amount of memory originally allotted.751 /// When a block of memory is allotted for future updates, such as the memory allocated to hold discretionary access control and primary group information, successive updates might exceed the amount of memory originally allotted.
1097 /// Because a quota might already have been charged to several processes that have handles to the object, it is not reasonable to alter the size of the allocated memory.752 /// Because a quota might already have been charged to several processes that have handles to the object, it is not reasonable to alter the size of the allocated memory.
1098 /// Instead, a request that requires more memory than has been allotted must fail and the STATUS_ALLOTTED_SPACE_EXCEEDED error returned.753 /// Instead, a request that requires more memory than has been allotted must fail and the STATUS_ALLOTTED_SPACE_EXCEEDED error returned.
1099 ALLOTTED_SPACE_EXCEEDED = 0xC0000099,754 ALLOTTED_SPACE_EXCEEDED = 0xC0000099,
1100
1101 /// Insufficient system resources exist to complete the API.755 /// Insufficient system resources exist to complete the API.
1102 INSUFFICIENT_RESOURCES = 0xC000009A,756 INSUFFICIENT_RESOURCES = 0xC000009A,
1103
1104 /// An attempt has been made to open a DFS exit path control file.757 /// An attempt has been made to open a DFS exit path control file.
1105 DFS_EXIT_PATH_FOUND = 0xC000009B,758 DFS_EXIT_PATH_FOUND = 0xC000009B,
1106
1107 /// There are bad blocks (sectors) on the hard disk.759 /// There are bad blocks (sectors) on the hard disk.
1108 DEVICE_DATA_ERROR = 0xC000009C,760 DEVICE_DATA_ERROR = 0xC000009C,
1109
1110 /// There is bad cabling, non-termination, or the controller is not able to obtain access to the hard disk.761 /// There is bad cabling, non-termination, or the controller is not able to obtain access to the hard disk.
1111 DEVICE_NOT_CONNECTED = 0xC000009D,762 DEVICE_NOT_CONNECTED = 0xC000009D,
1112
1113 /// Virtual memory cannot be freed because the base address is not the base of the region and a region size of zero was specified.763 /// Virtual memory cannot be freed because the base address is not the base of the region and a region size of zero was specified.
1114 FREE_VM_NOT_AT_BASE = 0xC000009F,764 FREE_VM_NOT_AT_BASE = 0xC000009F,
1115
1116 /// An attempt was made to free virtual memory that is not allocated.765 /// An attempt was made to free virtual memory that is not allocated.
1117 MEMORY_NOT_ALLOCATED = 0xC00000A0,766 MEMORY_NOT_ALLOCATED = 0xC00000A0,
1118
1119 /// The working set is not big enough to allow the requested pages to be locked.767 /// The working set is not big enough to allow the requested pages to be locked.
1120 WORKING_SET_QUOTA = 0xC00000A1,768 WORKING_SET_QUOTA = 0xC00000A1,
1121
1122 /// {Write Protect Error} The disk cannot be written to because it is write-protected.769 /// {Write Protect Error} The disk cannot be written to because it is write-protected.
1123 /// Remove the write protection from the volume %hs in drive %hs.770 /// Remove the write protection from the volume %hs in drive %hs.
1124 MEDIA_WRITE_PROTECTED = 0xC00000A2,771 MEDIA_WRITE_PROTECTED = 0xC00000A2,
1125
1126 /// {Drive Not Ready} The drive is not ready for use; its door might be open.772 /// {Drive Not Ready} The drive is not ready for use; its door might be open.
1127 /// Check drive %hs and make sure that a disk is inserted and that the drive door is closed.773 /// Check drive %hs and make sure that a disk is inserted and that the drive door is closed.
1128 DEVICE_NOT_READY = 0xC00000A3,774 DEVICE_NOT_READY = 0xC00000A3,
1129
1130 /// The specified attributes are invalid or are incompatible with the attributes for the group as a whole.775 /// The specified attributes are invalid or are incompatible with the attributes for the group as a whole.
1131 INVALID_GROUP_ATTRIBUTES = 0xC00000A4,776 INVALID_GROUP_ATTRIBUTES = 0xC00000A4,
1132
1133 /// A specified impersonation level is invalid.777 /// A specified impersonation level is invalid.
1134 /// Also used to indicate that a required impersonation level was not provided.778 /// Also used to indicate that a required impersonation level was not provided.
1135 BAD_IMPERSONATION_LEVEL = 0xC00000A5,779 BAD_IMPERSONATION_LEVEL = 0xC00000A5,
1136
1137 /// An attempt was made to open an anonymous-level token. Anonymous tokens cannot be opened.780 /// An attempt was made to open an anonymous-level token. Anonymous tokens cannot be opened.
1138 CANT_OPEN_ANONYMOUS = 0xC00000A6,781 CANT_OPEN_ANONYMOUS = 0xC00000A6,
1139
1140 /// The validation information class requested was invalid.782 /// The validation information class requested was invalid.
1141 BAD_VALIDATION_CLASS = 0xC00000A7,783 BAD_VALIDATION_CLASS = 0xC00000A7,
1142
1143 /// The type of a token object is inappropriate for its attempted use.784 /// The type of a token object is inappropriate for its attempted use.
1144 BAD_TOKEN_TYPE = 0xC00000A8,785 BAD_TOKEN_TYPE = 0xC00000A8,
1145
1146 /// The type of a token object is inappropriate for its attempted use.786 /// The type of a token object is inappropriate for its attempted use.
1147 BAD_MASTER_BOOT_RECORD = 0xC00000A9,787 BAD_MASTER_BOOT_RECORD = 0xC00000A9,
1148
1149 /// An attempt was made to execute an instruction at an unaligned address and the host system does not support unaligned instruction references.788 /// An attempt was made to execute an instruction at an unaligned address and the host system does not support unaligned instruction references.
1150 INSTRUCTION_MISALIGNMENT = 0xC00000AA,789 INSTRUCTION_MISALIGNMENT = 0xC00000AA,
1151
1152 /// The maximum named pipe instance count has been reached.790 /// The maximum named pipe instance count has been reached.
1153 INSTANCE_NOT_AVAILABLE = 0xC00000AB,791 INSTANCE_NOT_AVAILABLE = 0xC00000AB,
1154
1155 /// An instance of a named pipe cannot be found in the listening state.792 /// An instance of a named pipe cannot be found in the listening state.
1156 PIPE_NOT_AVAILABLE = 0xC00000AC,793 PIPE_NOT_AVAILABLE = 0xC00000AC,
1157
1158 /// The named pipe is not in the connected or closing state.794 /// The named pipe is not in the connected or closing state.
1159 INVALID_PIPE_STATE = 0xC00000AD,795 INVALID_PIPE_STATE = 0xC00000AD,
1160
1161 /// The specified pipe is set to complete operations and there are current I/O operations queued so that it cannot be changed to queue operations.796 /// The specified pipe is set to complete operations and there are current I/O operations queued so that it cannot be changed to queue operations.
1162 PIPE_BUSY = 0xC00000AE,797 PIPE_BUSY = 0xC00000AE,
1163
1164 /// The specified handle is not open to the server end of the named pipe.798 /// The specified handle is not open to the server end of the named pipe.
1165 ILLEGAL_FUNCTION = 0xC00000AF,799 ILLEGAL_FUNCTION = 0xC00000AF,
1166
1167 /// The specified named pipe is in the disconnected state.800 /// The specified named pipe is in the disconnected state.
1168 PIPE_DISCONNECTED = 0xC00000B0,801 PIPE_DISCONNECTED = 0xC00000B0,
1169
1170 /// The specified named pipe is in the closing state.802 /// The specified named pipe is in the closing state.
1171 PIPE_CLOSING = 0xC00000B1,803 PIPE_CLOSING = 0xC00000B1,
1172
1173 /// The specified named pipe is in the connected state.804 /// The specified named pipe is in the connected state.
1174 PIPE_CONNECTED = 0xC00000B2,805 PIPE_CONNECTED = 0xC00000B2,
1175
1176 /// The specified named pipe is in the listening state.806 /// The specified named pipe is in the listening state.
1177 PIPE_LISTENING = 0xC00000B3,807 PIPE_LISTENING = 0xC00000B3,
1178
1179 /// The specified named pipe is not in message mode.808 /// The specified named pipe is not in message mode.
1180 INVALID_READ_MODE = 0xC00000B4,809 INVALID_READ_MODE = 0xC00000B4,
1181
1182 /// {Device Timeout} The specified I/O operation on %hs was not completed before the time-out period expired.810 /// {Device Timeout} The specified I/O operation on %hs was not completed before the time-out period expired.
1183 IO_TIMEOUT = 0xC00000B5,811 IO_TIMEOUT = 0xC00000B5,
1184
1185 /// The specified file has been closed by another process.812 /// The specified file has been closed by another process.
1186 FILE_FORCED_CLOSED = 0xC00000B6,813 FILE_FORCED_CLOSED = 0xC00000B6,
1187
1188 /// Profiling is not started.814 /// Profiling is not started.
1189 PROFILING_NOT_STARTED = 0xC00000B7,815 PROFILING_NOT_STARTED = 0xC00000B7,
1190
1191 /// Profiling is not stopped.816 /// Profiling is not stopped.
1192 PROFILING_NOT_STOPPED = 0xC00000B8,817 PROFILING_NOT_STOPPED = 0xC00000B8,
1193
1194 /// The passed ACL did not contain the minimum required information.818 /// The passed ACL did not contain the minimum required information.
1195 COULD_NOT_INTERPRET = 0xC00000B9,819 COULD_NOT_INTERPRET = 0xC00000B9,
1196
1197 /// The file that was specified as a target is a directory, and the caller specified that it could be anything but a directory.820 /// The file that was specified as a target is a directory, and the caller specified that it could be anything but a directory.
1198 FILE_IS_A_DIRECTORY = 0xC00000BA,821 FILE_IS_A_DIRECTORY = 0xC00000BA,
1199
1200 /// The request is not supported.822 /// The request is not supported.
1201 NOT_SUPPORTED = 0xC00000BB,823 NOT_SUPPORTED = 0xC00000BB,
1202
1203 /// This remote computer is not listening.824 /// This remote computer is not listening.
1204 REMOTE_NOT_LISTENING = 0xC00000BC,825 REMOTE_NOT_LISTENING = 0xC00000BC,
1205
1206 /// A duplicate name exists on the network.826 /// A duplicate name exists on the network.
1207 DUPLICATE_NAME = 0xC00000BD,827 DUPLICATE_NAME = 0xC00000BD,
1208
1209 /// The network path cannot be located.828 /// The network path cannot be located.
1210 BAD_NETWORK_PATH = 0xC00000BE,829 BAD_NETWORK_PATH = 0xC00000BE,
1211
1212 /// The network is busy.830 /// The network is busy.
1213 NETWORK_BUSY = 0xC00000BF,831 NETWORK_BUSY = 0xC00000BF,
1214
1215 /// This device does not exist.832 /// This device does not exist.
1216 DEVICE_DOES_NOT_EXIST = 0xC00000C0,833 DEVICE_DOES_NOT_EXIST = 0xC00000C0,
1217
1218 /// The network BIOS command limit has been reached.834 /// The network BIOS command limit has been reached.
1219 TOO_MANY_COMMANDS = 0xC00000C1,835 TOO_MANY_COMMANDS = 0xC00000C1,
1220
1221 /// An I/O adapter hardware error has occurred.836 /// An I/O adapter hardware error has occurred.
1222 ADAPTER_HARDWARE_ERROR = 0xC00000C2,837 ADAPTER_HARDWARE_ERROR = 0xC00000C2,
1223
1224 /// The network responded incorrectly.838 /// The network responded incorrectly.
1225 INVALID_NETWORK_RESPONSE = 0xC00000C3,839 INVALID_NETWORK_RESPONSE = 0xC00000C3,
1226
1227 /// An unexpected network error occurred.840 /// An unexpected network error occurred.
1228 UNEXPECTED_NETWORK_ERROR = 0xC00000C4,841 UNEXPECTED_NETWORK_ERROR = 0xC00000C4,
1229
1230 /// The remote adapter is not compatible.842 /// The remote adapter is not compatible.
1231 BAD_REMOTE_ADAPTER = 0xC00000C5,843 BAD_REMOTE_ADAPTER = 0xC00000C5,
1232
1233 /// The print queue is full.844 /// The print queue is full.
1234 PRINT_QUEUE_FULL = 0xC00000C6,845 PRINT_QUEUE_FULL = 0xC00000C6,
1235
1236 /// Space to store the file that is waiting to be printed is not available on the server.846 /// Space to store the file that is waiting to be printed is not available on the server.
1237 NO_SPOOL_SPACE = 0xC00000C7,847 NO_SPOOL_SPACE = 0xC00000C7,
1238
1239 /// The requested print file has been canceled.848 /// The requested print file has been canceled.
1240 PRINT_CANCELLED = 0xC00000C8,849 PRINT_CANCELLED = 0xC00000C8,
1241
1242 /// The network name was deleted.850 /// The network name was deleted.
1243 NETWORK_NAME_DELETED = 0xC00000C9,851 NETWORK_NAME_DELETED = 0xC00000C9,
1244
1245 /// Network access is denied.852 /// Network access is denied.
1246 NETWORK_ACCESS_DENIED = 0xC00000CA,853 NETWORK_ACCESS_DENIED = 0xC00000CA,
1247
1248 /// {Incorrect Network Resource Type} The specified device type (LPT, for example) conflicts with the actual device type on the remote resource.854 /// {Incorrect Network Resource Type} The specified device type (LPT, for example) conflicts with the actual device type on the remote resource.
1249 BAD_DEVICE_TYPE = 0xC00000CB,855 BAD_DEVICE_TYPE = 0xC00000CB,
1250
1251 /// {Network Name Not Found} The specified share name cannot be found on the remote server.856 /// {Network Name Not Found} The specified share name cannot be found on the remote server.
1252 BAD_NETWORK_NAME = 0xC00000CC,857 BAD_NETWORK_NAME = 0xC00000CC,
1253
1254 /// The name limit for the network adapter card of the local computer was exceeded.858 /// The name limit for the network adapter card of the local computer was exceeded.
1255 TOO_MANY_NAMES = 0xC00000CD,859 TOO_MANY_NAMES = 0xC00000CD,
1256
1257 /// The network BIOS session limit was exceeded.860 /// The network BIOS session limit was exceeded.
1258 TOO_MANY_SESSIONS = 0xC00000CE,861 TOO_MANY_SESSIONS = 0xC00000CE,
1259
1260 /// File sharing has been temporarily paused.862 /// File sharing has been temporarily paused.
1261 SHARING_PAUSED = 0xC00000CF,863 SHARING_PAUSED = 0xC00000CF,
1262
1263 /// No more connections can be made to this remote computer at this time because the computer has already accepted the maximum number of connections.864 /// No more connections can be made to this remote computer at this time because the computer has already accepted the maximum number of connections.
1264 REQUEST_NOT_ACCEPTED = 0xC00000D0,865 REQUEST_NOT_ACCEPTED = 0xC00000D0,
1265
1266 /// Print or disk redirection is temporarily paused.866 /// Print or disk redirection is temporarily paused.
1267 REDIRECTOR_PAUSED = 0xC00000D1,867 REDIRECTOR_PAUSED = 0xC00000D1,
1268
1269 /// A network data fault occurred.868 /// A network data fault occurred.
1270 NET_WRITE_FAULT = 0xC00000D2,869 NET_WRITE_FAULT = 0xC00000D2,
1271
1272 /// The number of active profiling objects is at the maximum and no more can be started.870 /// The number of active profiling objects is at the maximum and no more can be started.
1273 PROFILING_AT_LIMIT = 0xC00000D3,871 PROFILING_AT_LIMIT = 0xC00000D3,
1274
1275 /// {Incorrect Volume} The destination file of a rename request is located on a different device than the source of the rename request.872 /// {Incorrect Volume} The destination file of a rename request is located on a different device than the source of the rename request.
1276 NOT_SAME_DEVICE = 0xC00000D4,873 NOT_SAME_DEVICE = 0xC00000D4,
1277
1278 /// The specified file has been renamed and thus cannot be modified.874 /// The specified file has been renamed and thus cannot be modified.
1279 FILE_RENAMED = 0xC00000D5,875 FILE_RENAMED = 0xC00000D5,
1280
1281 /// {Network Request Timeout} The session with a remote server has been disconnected because the time-out interval for a request has expired.876 /// {Network Request Timeout} The session with a remote server has been disconnected because the time-out interval for a request has expired.
1282 VIRTUAL_CIRCUIT_CLOSED = 0xC00000D6,877 VIRTUAL_CIRCUIT_CLOSED = 0xC00000D6,
1283
1284 /// Indicates an attempt was made to operate on the security of an object that does not have security associated with it.878 /// Indicates an attempt was made to operate on the security of an object that does not have security associated with it.
1285 NO_SECURITY_ON_OBJECT = 0xC00000D7,879 NO_SECURITY_ON_OBJECT = 0xC00000D7,
1286
1287 /// Used to indicate that an operation cannot continue without blocking for I/O.880 /// Used to indicate that an operation cannot continue without blocking for I/O.
1288 CANT_WAIT = 0xC00000D8,881 CANT_WAIT = 0xC00000D8,
1289
1290 /// Used to indicate that a read operation was done on an empty pipe.882 /// Used to indicate that a read operation was done on an empty pipe.
1291 PIPE_EMPTY = 0xC00000D9,883 PIPE_EMPTY = 0xC00000D9,
1292
1293 /// Configuration information could not be read from the domain controller, either because the machine is unavailable or access has been denied.884 /// Configuration information could not be read from the domain controller, either because the machine is unavailable or access has been denied.
1294 CANT_ACCESS_DOMAIN_INFO = 0xC00000DA,885 CANT_ACCESS_DOMAIN_INFO = 0xC00000DA,
1295
1296 /// Indicates that a thread attempted to terminate itself by default (called NtTerminateThread with NULL) and it was the last thread in the current process.886 /// Indicates that a thread attempted to terminate itself by default (called NtTerminateThread with NULL) and it was the last thread in the current process.
1297 CANT_TERMINATE_SELF = 0xC00000DB,887 CANT_TERMINATE_SELF = 0xC00000DB,
1298
1299 /// Indicates the Sam Server was in the wrong state to perform the desired operation.888 /// Indicates the Sam Server was in the wrong state to perform the desired operation.
1300 INVALID_SERVER_STATE = 0xC00000DC,889 INVALID_SERVER_STATE = 0xC00000DC,
1301
1302 /// Indicates the domain was in the wrong state to perform the desired operation.890 /// Indicates the domain was in the wrong state to perform the desired operation.
1303 INVALID_DOMAIN_STATE = 0xC00000DD,891 INVALID_DOMAIN_STATE = 0xC00000DD,
1304
1305 /// This operation is only allowed for the primary domain controller of the domain.892 /// This operation is only allowed for the primary domain controller of the domain.
1306 INVALID_DOMAIN_ROLE = 0xC00000DE,893 INVALID_DOMAIN_ROLE = 0xC00000DE,
1307
1308 /// The specified domain did not exist.894 /// The specified domain did not exist.
1309 NO_SUCH_DOMAIN = 0xC00000DF,895 NO_SUCH_DOMAIN = 0xC00000DF,
1310
1311 /// The specified domain already exists.896 /// The specified domain already exists.
1312 DOMAIN_EXISTS = 0xC00000E0,897 DOMAIN_EXISTS = 0xC00000E0,
1313
1314 /// An attempt was made to exceed the limit on the number of domains per server for this release.898 /// An attempt was made to exceed the limit on the number of domains per server for this release.
1315 DOMAIN_LIMIT_EXCEEDED = 0xC00000E1,899 DOMAIN_LIMIT_EXCEEDED = 0xC00000E1,
1316
1317 /// An error status returned when the opportunistic lock (oplock) request is denied.900 /// An error status returned when the opportunistic lock (oplock) request is denied.
1318 OPLOCK_NOT_GRANTED = 0xC00000E2,901 OPLOCK_NOT_GRANTED = 0xC00000E2,
1319
1320 /// An error status returned when an invalid opportunistic lock (oplock) acknowledgment is received by a file system.902 /// An error status returned when an invalid opportunistic lock (oplock) acknowledgment is received by a file system.
1321 INVALID_OPLOCK_PROTOCOL = 0xC00000E3,903 INVALID_OPLOCK_PROTOCOL = 0xC00000E3,
1322
1323 /// This error indicates that the requested operation cannot be completed due to a catastrophic media failure or an on-disk data structure corruption.904 /// This error indicates that the requested operation cannot be completed due to a catastrophic media failure or an on-disk data structure corruption.
1324 INTERNAL_DB_CORRUPTION = 0xC00000E4,905 INTERNAL_DB_CORRUPTION = 0xC00000E4,
1325
1326 /// An internal error occurred.906 /// An internal error occurred.
1327 INTERNAL_ERROR = 0xC00000E5,907 INTERNAL_ERROR = 0xC00000E5,
1328
1329 /// Indicates generic access types were contained in an access mask which should already be mapped to non-generic access types.908 /// Indicates generic access types were contained in an access mask which should already be mapped to non-generic access types.
1330 GENERIC_NOT_MAPPED = 0xC00000E6,909 GENERIC_NOT_MAPPED = 0xC00000E6,
1331
1332 /// Indicates a security descriptor is not in the necessary format (absolute or self-relative).910 /// Indicates a security descriptor is not in the necessary format (absolute or self-relative).
1333 BAD_DESCRIPTOR_FORMAT = 0xC00000E7,911 BAD_DESCRIPTOR_FORMAT = 0xC00000E7,
1334
1335 /// An access to a user buffer failed at an expected point in time.912 /// An access to a user buffer failed at an expected point in time.
1336 /// This code is defined because the caller does not want to accept STATUS_ACCESS_VIOLATION in its filter.913 /// This code is defined because the caller does not want to accept STATUS_ACCESS_VIOLATION in its filter.
1337 INVALID_USER_BUFFER = 0xC00000E8,914 INVALID_USER_BUFFER = 0xC00000E8,
1338
1339 /// If an I/O error that is not defined in the standard FsRtl filter is returned, it is converted to the following error, which is guaranteed to be in the filter.915 /// If an I/O error that is not defined in the standard FsRtl filter is returned, it is converted to the following error, which is guaranteed to be in the filter.
1340 /// In this case, information is lost; however, the filter correctly handles the exception.916 /// In this case, information is lost; however, the filter correctly handles the exception.
1341 UNEXPECTED_IO_ERROR = 0xC00000E9,917 UNEXPECTED_IO_ERROR = 0xC00000E9,
1342
1343 /// If an MM error that is not defined in the standard FsRtl filter is returned, it is converted to one of the following errors, which are guaranteed to be in the filter.918 /// If an MM error that is not defined in the standard FsRtl filter is returned, it is converted to one of the following errors, which are guaranteed to be in the filter.
1344 /// In this case, information is lost; however, the filter correctly handles the exception.919 /// In this case, information is lost; however, the filter correctly handles the exception.
1345 UNEXPECTED_MM_CREATE_ERR = 0xC00000EA,920 UNEXPECTED_MM_CREATE_ERR = 0xC00000EA,
1346
1347 /// If an MM error that is not defined in the standard FsRtl filter is returned, it is converted to one of the following errors, which are guaranteed to be in the filter.921 /// If an MM error that is not defined in the standard FsRtl filter is returned, it is converted to one of the following errors, which are guaranteed to be in the filter.
1348 /// In this case, information is lost; however, the filter correctly handles the exception.922 /// In this case, information is lost; however, the filter correctly handles the exception.
1349 UNEXPECTED_MM_MAP_ERROR = 0xC00000EB,923 UNEXPECTED_MM_MAP_ERROR = 0xC00000EB,
1350
1351 /// If an MM error that is not defined in the standard FsRtl filter is returned, it is converted to one of the following errors, which are guaranteed to be in the filter.924 /// If an MM error that is not defined in the standard FsRtl filter is returned, it is converted to one of the following errors, which are guaranteed to be in the filter.
1352 /// In this case, information is lost; however, the filter correctly handles the exception.925 /// In this case, information is lost; however, the filter correctly handles the exception.
1353 UNEXPECTED_MM_EXTEND_ERR = 0xC00000EC,926 UNEXPECTED_MM_EXTEND_ERR = 0xC00000EC,
1354
1355 /// The requested action is restricted for use by logon processes only.927 /// The requested action is restricted for use by logon processes only.
1356 /// The calling process has not registered as a logon process.928 /// The calling process has not registered as a logon process.
1357 NOT_LOGON_PROCESS = 0xC00000ED,929 NOT_LOGON_PROCESS = 0xC00000ED,
1358
1359 /// An attempt has been made to start a new session manager or LSA logon session by using an ID that is already in use.930 /// An attempt has been made to start a new session manager or LSA logon session by using an ID that is already in use.
1360 LOGON_SESSION_EXISTS = 0xC00000EE,931 LOGON_SESSION_EXISTS = 0xC00000EE,
1361
1362 /// An invalid parameter was passed to a service or function as the first argument.932 /// An invalid parameter was passed to a service or function as the first argument.
1363 INVALID_PARAMETER_1 = 0xC00000EF,933 INVALID_PARAMETER_1 = 0xC00000EF,
1364
1365 /// An invalid parameter was passed to a service or function as the second argument.934 /// An invalid parameter was passed to a service or function as the second argument.
1366 INVALID_PARAMETER_2 = 0xC00000F0,935 INVALID_PARAMETER_2 = 0xC00000F0,
1367
1368 /// An invalid parameter was passed to a service or function as the third argument.936 /// An invalid parameter was passed to a service or function as the third argument.
1369 INVALID_PARAMETER_3 = 0xC00000F1,937 INVALID_PARAMETER_3 = 0xC00000F1,
1370
1371 /// An invalid parameter was passed to a service or function as the fourth argument.938 /// An invalid parameter was passed to a service or function as the fourth argument.
1372 INVALID_PARAMETER_4 = 0xC00000F2,939 INVALID_PARAMETER_4 = 0xC00000F2,
1373
1374 /// An invalid parameter was passed to a service or function as the fifth argument.940 /// An invalid parameter was passed to a service or function as the fifth argument.
1375 INVALID_PARAMETER_5 = 0xC00000F3,941 INVALID_PARAMETER_5 = 0xC00000F3,
1376
1377 /// An invalid parameter was passed to a service or function as the sixth argument.942 /// An invalid parameter was passed to a service or function as the sixth argument.
1378 INVALID_PARAMETER_6 = 0xC00000F4,943 INVALID_PARAMETER_6 = 0xC00000F4,
1379
1380 /// An invalid parameter was passed to a service or function as the seventh argument.944 /// An invalid parameter was passed to a service or function as the seventh argument.
1381 INVALID_PARAMETER_7 = 0xC00000F5,945 INVALID_PARAMETER_7 = 0xC00000F5,
1382
1383 /// An invalid parameter was passed to a service or function as the eighth argument.946 /// An invalid parameter was passed to a service or function as the eighth argument.
1384 INVALID_PARAMETER_8 = 0xC00000F6,947 INVALID_PARAMETER_8 = 0xC00000F6,
1385
1386 /// An invalid parameter was passed to a service or function as the ninth argument.948 /// An invalid parameter was passed to a service or function as the ninth argument.
1387 INVALID_PARAMETER_9 = 0xC00000F7,949 INVALID_PARAMETER_9 = 0xC00000F7,
1388
1389 /// An invalid parameter was passed to a service or function as the tenth argument.950 /// An invalid parameter was passed to a service or function as the tenth argument.
1390 INVALID_PARAMETER_10 = 0xC00000F8,951 INVALID_PARAMETER_10 = 0xC00000F8,
1391
1392 /// An invalid parameter was passed to a service or function as the eleventh argument.952 /// An invalid parameter was passed to a service or function as the eleventh argument.
1393 INVALID_PARAMETER_11 = 0xC00000F9,953 INVALID_PARAMETER_11 = 0xC00000F9,
1394
1395 /// An invalid parameter was passed to a service or function as the twelfth argument.954 /// An invalid parameter was passed to a service or function as the twelfth argument.
1396 INVALID_PARAMETER_12 = 0xC00000FA,955 INVALID_PARAMETER_12 = 0xC00000FA,
1397
1398 /// An attempt was made to access a network file, but the network software was not yet started.956 /// An attempt was made to access a network file, but the network software was not yet started.
1399 REDIRECTOR_NOT_STARTED = 0xC00000FB,957 REDIRECTOR_NOT_STARTED = 0xC00000FB,
1400
1401 /// An attempt was made to start the redirector, but the redirector has already been started.958 /// An attempt was made to start the redirector, but the redirector has already been started.
1402 REDIRECTOR_STARTED = 0xC00000FC,959 REDIRECTOR_STARTED = 0xC00000FC,
1403
1404 /// A new guard page for the stack cannot be created.960 /// A new guard page for the stack cannot be created.
1405 STACK_OVERFLOW = 0xC00000FD,961 STACK_OVERFLOW = 0xC00000FD,
1406
1407 /// A specified authentication package is unknown.962 /// A specified authentication package is unknown.
1408 NO_SUCH_PACKAGE = 0xC00000FE,963 NO_SUCH_PACKAGE = 0xC00000FE,
1409
1410 /// A malformed function table was encountered during an unwind operation.964 /// A malformed function table was encountered during an unwind operation.
1411 BAD_FUNCTION_TABLE = 0xC00000FF,965 BAD_FUNCTION_TABLE = 0xC00000FF,
1412
1413 /// Indicates the specified environment variable name was not found in the specified environment block.966 /// Indicates the specified environment variable name was not found in the specified environment block.
1414 VARIABLE_NOT_FOUND = 0xC0000100,967 VARIABLE_NOT_FOUND = 0xC0000100,
1415
1416 /// Indicates that the directory trying to be deleted is not empty.968 /// Indicates that the directory trying to be deleted is not empty.
1417 DIRECTORY_NOT_EMPTY = 0xC0000101,969 DIRECTORY_NOT_EMPTY = 0xC0000101,
1418
1419 /// {Corrupt File} The file or directory %hs is corrupt and unreadable. Run the Chkdsk utility.970 /// {Corrupt File} The file or directory %hs is corrupt and unreadable. Run the Chkdsk utility.
1420 FILE_CORRUPT_ERROR = 0xC0000102,971 FILE_CORRUPT_ERROR = 0xC0000102,
1421
1422 /// A requested opened file is not a directory.972 /// A requested opened file is not a directory.
1423 NOT_A_DIRECTORY = 0xC0000103,973 NOT_A_DIRECTORY = 0xC0000103,
1424
1425 /// The logon session is not in a state that is consistent with the requested operation.974 /// The logon session is not in a state that is consistent with the requested operation.
1426 BAD_LOGON_SESSION_STATE = 0xC0000104,975 BAD_LOGON_SESSION_STATE = 0xC0000104,
1427
1428 /// An internal LSA error has occurred.976 /// An internal LSA error has occurred.
1429 /// An authentication package has requested the creation of a logon session but the ID of an already existing logon session has been specified.977 /// An authentication package has requested the creation of a logon session but the ID of an already existing logon session has been specified.
1430 LOGON_SESSION_COLLISION = 0xC0000105,978 LOGON_SESSION_COLLISION = 0xC0000105,
1431
1432 /// A specified name string is too long for its intended use.979 /// A specified name string is too long for its intended use.
1433 NAME_TOO_LONG = 0xC0000106,980 NAME_TOO_LONG = 0xC0000106,
1434
1435 /// The user attempted to force close the files on a redirected drive, but there were opened files on the drive, and the user did not specify a sufficient level of force.981 /// The user attempted to force close the files on a redirected drive, but there were opened files on the drive, and the user did not specify a sufficient level of force.
1436 FILES_OPEN = 0xC0000107,982 FILES_OPEN = 0xC0000107,
1437
1438 /// The user attempted to force close the files on a redirected drive, but there were opened directories on the drive, and the user did not specify a sufficient level of force.983 /// The user attempted to force close the files on a redirected drive, but there were opened directories on the drive, and the user did not specify a sufficient level of force.
1439 CONNECTION_IN_USE = 0xC0000108,984 CONNECTION_IN_USE = 0xC0000108,
1440
1441 /// RtlFindMessage could not locate the requested message ID in the message table resource.985 /// RtlFindMessage could not locate the requested message ID in the message table resource.
1442 MESSAGE_NOT_FOUND = 0xC0000109,986 MESSAGE_NOT_FOUND = 0xC0000109,
1443
1444 /// An attempt was made to duplicate an object handle into or out of an exiting process.987 /// An attempt was made to duplicate an object handle into or out of an exiting process.
1445 PROCESS_IS_TERMINATING = 0xC000010A,988 PROCESS_IS_TERMINATING = 0xC000010A,
1446
1447 /// Indicates an invalid value has been provided for the LogonType requested.989 /// Indicates an invalid value has been provided for the LogonType requested.
1448 INVALID_LOGON_TYPE = 0xC000010B,990 INVALID_LOGON_TYPE = 0xC000010B,
1449
1450 /// Indicates that an attempt was made to assign protection to a file system file or directory and one of the SIDs in the security descriptor could not be translated into a GUID that could be stored by the file system.991 /// Indicates that an attempt was made to assign protection to a file system file or directory and one of the SIDs in the security descriptor could not be translated into a GUID that could be stored by the file system.
1451 /// This causes the protection attempt to fail, which might cause a file creation attempt to fail.992 /// This causes the protection attempt to fail, which might cause a file creation attempt to fail.
1452 NO_GUID_TRANSLATION = 0xC000010C,993 NO_GUID_TRANSLATION = 0xC000010C,
1453
1454 /// Indicates that an attempt has been made to impersonate via a named pipe that has not yet been read from.994 /// Indicates that an attempt has been made to impersonate via a named pipe that has not yet been read from.
1455 CANNOT_IMPERSONATE = 0xC000010D,995 CANNOT_IMPERSONATE = 0xC000010D,
1456
1457 /// Indicates that the specified image is already loaded.996 /// Indicates that the specified image is already loaded.
1458 IMAGE_ALREADY_LOADED = 0xC000010E,997 IMAGE_ALREADY_LOADED = 0xC000010E,
1459
1460 /// Indicates that an attempt was made to change the size of the LDT for a process that has no LDT.998 /// Indicates that an attempt was made to change the size of the LDT for a process that has no LDT.
1461 NO_LDT = 0xC0000117,999 NO_LDT = 0xC0000117,
1462
1463 /// Indicates that an attempt was made to grow an LDT by setting its size, or that the size was not an even number of selectors.1000 /// Indicates that an attempt was made to grow an LDT by setting its size, or that the size was not an even number of selectors.
1464 INVALID_LDT_SIZE = 0xC0000118,1001 INVALID_LDT_SIZE = 0xC0000118,
1465
1466 /// Indicates that the starting value for the LDT information was not an integral multiple of the selector size.1002 /// Indicates that the starting value for the LDT information was not an integral multiple of the selector size.
1467 INVALID_LDT_OFFSET = 0xC0000119,1003 INVALID_LDT_OFFSET = 0xC0000119,
1468
1469 /// Indicates that the user supplied an invalid descriptor when trying to set up LDT descriptors.1004 /// Indicates that the user supplied an invalid descriptor when trying to set up LDT descriptors.
1470 INVALID_LDT_DESCRIPTOR = 0xC000011A,1005 INVALID_LDT_DESCRIPTOR = 0xC000011A,
1471
1472 /// The specified image file did not have the correct format. It appears to be NE format.1006 /// The specified image file did not have the correct format. It appears to be NE format.
1473 INVALID_IMAGE_NE_FORMAT = 0xC000011B,1007 INVALID_IMAGE_NE_FORMAT = 0xC000011B,
1474
1475 /// Indicates that the transaction state of a registry subtree is incompatible with the requested operation.1008 /// Indicates that the transaction state of a registry subtree is incompatible with the requested operation.
1476 /// For example, a request has been made to start a new transaction with one already in progress, or a request has been made to apply a transaction when one is not currently in progress.1009 /// For example, a request has been made to start a new transaction with one already in progress, or a request has been made to apply a transaction when one is not currently in progress.
1477 RXACT_INVALID_STATE = 0xC000011C,1010 RXACT_INVALID_STATE = 0xC000011C,
1478
1479 /// Indicates an error has occurred during a registry transaction commit.1011 /// Indicates an error has occurred during a registry transaction commit.
1480 /// The database has been left in an unknown, but probably inconsistent, state.1012 /// The database has been left in an unknown, but probably inconsistent, state.
1481 /// The state of the registry transaction is left as COMMITTING.1013 /// The state of the registry transaction is left as COMMITTING.
1482 RXACT_COMMIT_FAILURE = 0xC000011D,1014 RXACT_COMMIT_FAILURE = 0xC000011D,
1483
1484 /// An attempt was made to map a file of size zero with the maximum size specified as zero.1015 /// An attempt was made to map a file of size zero with the maximum size specified as zero.
1485 MAPPED_FILE_SIZE_ZERO = 0xC000011E,1016 MAPPED_FILE_SIZE_ZERO = 0xC000011E,
1486
1487 /// Too many files are opened on a remote server.1017 /// Too many files are opened on a remote server.
1488 /// This error should only be returned by the Windows redirector on a remote drive.1018 /// This error should only be returned by the Windows redirector on a remote drive.
1489 TOO_MANY_OPENED_FILES = 0xC000011F,1019 TOO_MANY_OPENED_FILES = 0xC000011F,
1490
1491 /// The I/O request was canceled.1020 /// The I/O request was canceled.
1492 CANCELLED = 0xC0000120,1021 CANCELLED = 0xC0000120,
1493
1494 /// An attempt has been made to remove a file or directory that cannot be deleted.1022 /// An attempt has been made to remove a file or directory that cannot be deleted.
1495 CANNOT_DELETE = 0xC0000121,1023 CANNOT_DELETE = 0xC0000121,
1496
1497 /// Indicates a name that was specified as a remote computer name is syntactically invalid.1024 /// Indicates a name that was specified as a remote computer name is syntactically invalid.
1498 INVALID_COMPUTER_NAME = 0xC0000122,1025 INVALID_COMPUTER_NAME = 0xC0000122,
1499
1500 /// An I/O request other than close was performed on a file after it was deleted, which can only happen to a request that did not complete before the last handle was closed via NtClose.1026 /// An I/O request other than close was performed on a file after it was deleted, which can only happen to a request that did not complete before the last handle was closed via NtClose.
1501 FILE_DELETED = 0xC0000123,1027 FILE_DELETED = 0xC0000123,
1502
1503 /// Indicates an operation that is incompatible with built-in accounts has been attempted on a built-in (special) SAM account. For example, built-in accounts cannot be deleted.1028 /// Indicates an operation that is incompatible with built-in accounts has been attempted on a built-in (special) SAM account. For example, built-in accounts cannot be deleted.
1504 SPECIAL_ACCOUNT = 0xC0000124,1029 SPECIAL_ACCOUNT = 0xC0000124,
1505
1506 /// The operation requested cannot be performed on the specified group because it is a built-in special group.1030 /// The operation requested cannot be performed on the specified group because it is a built-in special group.
1507 SPECIAL_GROUP = 0xC0000125,1031 SPECIAL_GROUP = 0xC0000125,
1508
1509 /// The operation requested cannot be performed on the specified user because it is a built-in special user.1032 /// The operation requested cannot be performed on the specified user because it is a built-in special user.
1510 SPECIAL_USER = 0xC0000126,1033 SPECIAL_USER = 0xC0000126,
1511
1512 /// Indicates a member cannot be removed from a group because the group is currently the member's primary group.1034 /// Indicates a member cannot be removed from a group because the group is currently the member's primary group.
1513 MEMBERS_PRIMARY_GROUP = 0xC0000127,1035 MEMBERS_PRIMARY_GROUP = 0xC0000127,
1514
1515 /// An I/O request other than close and several other special case operations was attempted using a file object that had already been closed.1036 /// An I/O request other than close and several other special case operations was attempted using a file object that had already been closed.
1516 FILE_CLOSED = 0xC0000128,1037 FILE_CLOSED = 0xC0000128,
1517
1518 /// Indicates a process has too many threads to perform the requested action.1038 /// Indicates a process has too many threads to perform the requested action.
1519 /// For example, assignment of a primary token can be performed only when a process has zero or one threads.1039 /// For example, assignment of a primary token can be performed only when a process has zero or one threads.
1520 TOO_MANY_THREADS = 0xC0000129,1040 TOO_MANY_THREADS = 0xC0000129,
1521
1522 /// An attempt was made to operate on a thread within a specific process, but the specified thread is not in the specified process.1041 /// An attempt was made to operate on a thread within a specific process, but the specified thread is not in the specified process.
1523 THREAD_NOT_IN_PROCESS = 0xC000012A,1042 THREAD_NOT_IN_PROCESS = 0xC000012A,
1524
1525 /// An attempt was made to establish a token for use as a primary token but the token is already in use.1043 /// An attempt was made to establish a token for use as a primary token but the token is already in use.
1526 /// A token can only be the primary token of one process at a time.1044 /// A token can only be the primary token of one process at a time.
1527 TOKEN_ALREADY_IN_USE = 0xC000012B,1045 TOKEN_ALREADY_IN_USE = 0xC000012B,
1528
1529 /// The page file quota was exceeded.1046 /// The page file quota was exceeded.
1530 PAGEFILE_QUOTA_EXCEEDED = 0xC000012C,1047 PAGEFILE_QUOTA_EXCEEDED = 0xC000012C,
1531
1532 /// {Out of Virtual Memory} Your system is low on virtual memory.1048 /// {Out of Virtual Memory} Your system is low on virtual memory.
1533 /// To ensure that Windows runs correctly, increase the size of your virtual memory paging file. For more information, see Help.1049 /// To ensure that Windows runs correctly, increase the size of your virtual memory paging file. For more information, see Help.
1534 COMMITMENT_LIMIT = 0xC000012D,1050 COMMITMENT_LIMIT = 0xC000012D,
1535
1536 /// The specified image file did not have the correct format: it appears to be LE format.1051 /// The specified image file did not have the correct format: it appears to be LE format.
1537 INVALID_IMAGE_LE_FORMAT = 0xC000012E,1052 INVALID_IMAGE_LE_FORMAT = 0xC000012E,
1538
1539 /// The specified image file did not have the correct format: it did not have an initial MZ.1053 /// The specified image file did not have the correct format: it did not have an initial MZ.
1540 INVALID_IMAGE_NOT_MZ = 0xC000012F,1054 INVALID_IMAGE_NOT_MZ = 0xC000012F,
1541
1542 /// The specified image file did not have the correct format: it did not have a proper e_lfarlc in the MZ header.1055 /// The specified image file did not have the correct format: it did not have a proper e_lfarlc in the MZ header.
1543 INVALID_IMAGE_PROTECT = 0xC0000130,1056 INVALID_IMAGE_PROTECT = 0xC0000130,
1544
1545 /// The specified image file did not have the correct format: it appears to be a 16-bit Windows image.1057 /// The specified image file did not have the correct format: it appears to be a 16-bit Windows image.
1546 INVALID_IMAGE_WIN_16 = 0xC0000131,1058 INVALID_IMAGE_WIN_16 = 0xC0000131,
1547
1548 /// The Netlogon service cannot start because another Netlogon service running in the domain conflicts with the specified role.1059 /// The Netlogon service cannot start because another Netlogon service running in the domain conflicts with the specified role.
1549 LOGON_SERVER_CONFLICT = 0xC0000132,1060 LOGON_SERVER_CONFLICT = 0xC0000132,
1550
1551 /// The time at the primary domain controller is different from the time at the backup domain controller or member server by too large an amount.1061 /// The time at the primary domain controller is different from the time at the backup domain controller or member server by too large an amount.
1552 TIME_DIFFERENCE_AT_DC = 0xC0000133,1062 TIME_DIFFERENCE_AT_DC = 0xC0000133,
1553
1554 /// On applicable Windows Server releases, the SAM database is significantly out of synchronization with the copy on the domain controller. A complete synchronization is required.1063 /// On applicable Windows Server releases, the SAM database is significantly out of synchronization with the copy on the domain controller. A complete synchronization is required.
1555 SYNCHRONIZATION_REQUIRED = 0xC0000134,1064 SYNCHRONIZATION_REQUIRED = 0xC0000134,
1556
1557 /// {Unable To Locate Component} This application has failed to start because %hs was not found.1065 /// {Unable To Locate Component} This application has failed to start because %hs was not found.
1558 /// Reinstalling the application might fix this problem.1066 /// Reinstalling the application might fix this problem.
1559 DLL_NOT_FOUND = 0xC0000135,1067 DLL_NOT_FOUND = 0xC0000135,
1560
1561 /// The NtCreateFile API failed. This error should never be returned to an application; it is a place holder for the Windows LAN Manager Redirector to use in its internal error-mapping routines.1068 /// The NtCreateFile API failed. This error should never be returned to an application; it is a place holder for the Windows LAN Manager Redirector to use in its internal error-mapping routines.
1562 OPEN_FAILED = 0xC0000136,1069 OPEN_FAILED = 0xC0000136,
1563
1564 /// {Privilege Failed} The I/O permissions for the process could not be changed.1070 /// {Privilege Failed} The I/O permissions for the process could not be changed.
1565 IO_PRIVILEGE_FAILED = 0xC0000137,1071 IO_PRIVILEGE_FAILED = 0xC0000137,
1566
1567 /// {Ordinal Not Found} The ordinal %ld could not be located in the dynamic link library %hs.1072 /// {Ordinal Not Found} The ordinal %ld could not be located in the dynamic link library %hs.
1568 ORDINAL_NOT_FOUND = 0xC0000138,1073 ORDINAL_NOT_FOUND = 0xC0000138,
1569
1570 /// {Entry Point Not Found} The procedure entry point %hs could not be located in the dynamic link library %hs.1074 /// {Entry Point Not Found} The procedure entry point %hs could not be located in the dynamic link library %hs.
1571 ENTRYPOINT_NOT_FOUND = 0xC0000139,1075 ENTRYPOINT_NOT_FOUND = 0xC0000139,
1572
1573 /// {Application Exit by CTRL+C} The application terminated as a result of a CTRL+C.1076 /// {Application Exit by CTRL+C} The application terminated as a result of a CTRL+C.
1574 CONTROL_C_EXIT = 0xC000013A,1077 CONTROL_C_EXIT = 0xC000013A,
1575
1576 /// {Virtual Circuit Closed} The network transport on your computer has closed a network connection.1078 /// {Virtual Circuit Closed} The network transport on your computer has closed a network connection.
1577 /// There might or might not be I/O requests outstanding.1079 /// There might or might not be I/O requests outstanding.
1578 LOCAL_DISCONNECT = 0xC000013B,1080 LOCAL_DISCONNECT = 0xC000013B,
1579
1580 /// {Virtual Circuit Closed} The network transport on a remote computer has closed a network connection.1081 /// {Virtual Circuit Closed} The network transport on a remote computer has closed a network connection.
1581 /// There might or might not be I/O requests outstanding.1082 /// There might or might not be I/O requests outstanding.
1582 REMOTE_DISCONNECT = 0xC000013C,1083 REMOTE_DISCONNECT = 0xC000013C,
1583
1584 /// {Insufficient Resources on Remote Computer} The remote computer has insufficient resources to complete the network request.1084 /// {Insufficient Resources on Remote Computer} The remote computer has insufficient resources to complete the network request.
1585 /// For example, the remote computer might not have enough available memory to carry out the request at this time.1085 /// For example, the remote computer might not have enough available memory to carry out the request at this time.
1586 REMOTE_RESOURCES = 0xC000013D,1086 REMOTE_RESOURCES = 0xC000013D,
1587
1588 /// {Virtual Circuit Closed} An existing connection (virtual circuit) has been broken at the remote computer.1087 /// {Virtual Circuit Closed} An existing connection (virtual circuit) has been broken at the remote computer.
1589 /// There is probably something wrong with the network software protocol or the network hardware on the remote computer.1088 /// There is probably something wrong with the network software protocol or the network hardware on the remote computer.
1590 LINK_FAILED = 0xC000013E,1089 LINK_FAILED = 0xC000013E,
1591
1592 /// {Virtual Circuit Closed} The network transport on your computer has closed a network connection because it had to wait too long for a response from the remote computer.1090 /// {Virtual Circuit Closed} The network transport on your computer has closed a network connection because it had to wait too long for a response from the remote computer.
1593 LINK_TIMEOUT = 0xC000013F,1091 LINK_TIMEOUT = 0xC000013F,
1594
1595 /// The connection handle that was given to the transport was invalid.1092 /// The connection handle that was given to the transport was invalid.
1596 INVALID_CONNECTION = 0xC0000140,1093 INVALID_CONNECTION = 0xC0000140,
1597
1598 /// The address handle that was given to the transport was invalid.1094 /// The address handle that was given to the transport was invalid.
1599 INVALID_ADDRESS = 0xC0000141,1095 INVALID_ADDRESS = 0xC0000141,
1600
1601 /// {DLL Initialization Failed} Initialization of the dynamic link library %hs failed. The process is terminating abnormally.1096 /// {DLL Initialization Failed} Initialization of the dynamic link library %hs failed. The process is terminating abnormally.
1602 DLL_INIT_FAILED = 0xC0000142,1097 DLL_INIT_FAILED = 0xC0000142,
1603
1604 /// {Missing System File} The required system file %hs is bad or missing.1098 /// {Missing System File} The required system file %hs is bad or missing.
1605 MISSING_SYSTEMFILE = 0xC0000143,1099 MISSING_SYSTEMFILE = 0xC0000143,
1606
1607 /// {Application Error} The exception %s (0x%08lx) occurred in the application at location 0x%08lx.1100 /// {Application Error} The exception %s (0x%08lx) occurred in the application at location 0x%08lx.
1608 UNHANDLED_EXCEPTION = 0xC0000144,1101 UNHANDLED_EXCEPTION = 0xC0000144,
1609
1610 /// {Application Error} The application failed to initialize properly (0x%lx). Click OK to terminate the application.1102 /// {Application Error} The application failed to initialize properly (0x%lx). Click OK to terminate the application.
1611 APP_INIT_FAILURE = 0xC0000145,1103 APP_INIT_FAILURE = 0xC0000145,
1612
1613 /// {Unable to Create Paging File} The creation of the paging file %hs failed (%lx). The requested size was %ld.1104 /// {Unable to Create Paging File} The creation of the paging file %hs failed (%lx). The requested size was %ld.
1614 PAGEFILE_CREATE_FAILED = 0xC0000146,1105 PAGEFILE_CREATE_FAILED = 0xC0000146,
1615
1616 /// {No Paging File Specified} No paging file was specified in the system configuration.1106 /// {No Paging File Specified} No paging file was specified in the system configuration.
1617 NO_PAGEFILE = 0xC0000147,1107 NO_PAGEFILE = 0xC0000147,
1618
1619 /// {Incorrect System Call Level} An invalid level was passed into the specified system call.1108 /// {Incorrect System Call Level} An invalid level was passed into the specified system call.
1620 INVALID_LEVEL = 0xC0000148,1109 INVALID_LEVEL = 0xC0000148,
1621
1622 /// {Incorrect Password to LAN Manager Server} You specified an incorrect password to a LAN Manager 2.x or MS-NET server.1110 /// {Incorrect Password to LAN Manager Server} You specified an incorrect password to a LAN Manager 2.x or MS-NET server.
1623 WRONG_PASSWORD_CORE = 0xC0000149,1111 WRONG_PASSWORD_CORE = 0xC0000149,
1624
1625 /// {EXCEPTION} A real-mode application issued a floating-point instruction and floating-point hardware is not present.1112 /// {EXCEPTION} A real-mode application issued a floating-point instruction and floating-point hardware is not present.
1626 ILLEGAL_FLOAT_CONTEXT = 0xC000014A,1113 ILLEGAL_FLOAT_CONTEXT = 0xC000014A,
1627
1628 /// The pipe operation has failed because the other end of the pipe has been closed.1114 /// The pipe operation has failed because the other end of the pipe has been closed.
1629 PIPE_BROKEN = 0xC000014B,1115 PIPE_BROKEN = 0xC000014B,
1630
1631 /// {The Registry Is Corrupt} The structure of one of the files that contains registry data is corrupt; the image of the file in memory is corrupt; or the file could not be recovered because the alternate copy or log was absent or corrupt.1116 /// {The Registry Is Corrupt} The structure of one of the files that contains registry data is corrupt; the image of the file in memory is corrupt; or the file could not be recovered because the alternate copy or log was absent or corrupt.
1632 REGISTRY_CORRUPT = 0xC000014C,1117 REGISTRY_CORRUPT = 0xC000014C,
1633
1634 /// An I/O operation initiated by the Registry failed and cannot be recovered.1118 /// An I/O operation initiated by the Registry failed and cannot be recovered.
1635 /// The registry could not read in, write out, or flush one of the files that contain the system's image of the registry.1119 /// The registry could not read in, write out, or flush one of the files that contain the system's image of the registry.
1636 REGISTRY_IO_FAILED = 0xC000014D,1120 REGISTRY_IO_FAILED = 0xC000014D,
1637
1638 /// An event pair synchronization operation was performed using the thread-specific client/server event pair object, but no event pair object was associated with the thread.1121 /// An event pair synchronization operation was performed using the thread-specific client/server event pair object, but no event pair object was associated with the thread.
1639 NO_EVENT_PAIR = 0xC000014E,1122 NO_EVENT_PAIR = 0xC000014E,
1640
1641 /// The volume does not contain a recognized file system.1123 /// The volume does not contain a recognized file system.
1642 /// Be sure that all required file system drivers are loaded and that the volume is not corrupt.1124 /// Be sure that all required file system drivers are loaded and that the volume is not corrupt.
1643 UNRECOGNIZED_VOLUME = 0xC000014F,1125 UNRECOGNIZED_VOLUME = 0xC000014F,
1644
1645 /// No serial device was successfully initialized. The serial driver will unload.1126 /// No serial device was successfully initialized. The serial driver will unload.
1646 SERIAL_NO_DEVICE_INITED = 0xC0000150,1127 SERIAL_NO_DEVICE_INITED = 0xC0000150,
1647
1648 /// The specified local group does not exist.1128 /// The specified local group does not exist.
1649 NO_SUCH_ALIAS = 0xC0000151,1129 NO_SUCH_ALIAS = 0xC0000151,
1650
1651 /// The specified account name is not a member of the group.1130 /// The specified account name is not a member of the group.
1652 MEMBER_NOT_IN_ALIAS = 0xC0000152,1131 MEMBER_NOT_IN_ALIAS = 0xC0000152,
1653
1654 /// The specified account name is already a member of the group.1132 /// The specified account name is already a member of the group.
1655 MEMBER_IN_ALIAS = 0xC0000153,1133 MEMBER_IN_ALIAS = 0xC0000153,
1656
1657 /// The specified local group already exists.1134 /// The specified local group already exists.
1658 ALIAS_EXISTS = 0xC0000154,1135 ALIAS_EXISTS = 0xC0000154,
1659
1660 /// A requested type of logon (for example, interactive, network, and service) is not granted by the local security policy of the target system.1136 /// A requested type of logon (for example, interactive, network, and service) is not granted by the local security policy of the target system.
1661 /// Ask the system administrator to grant the necessary form of logon.1137 /// Ask the system administrator to grant the necessary form of logon.
1662 LOGON_NOT_GRANTED = 0xC0000155,1138 LOGON_NOT_GRANTED = 0xC0000155,
1663
1664 /// The maximum number of secrets that can be stored in a single system was exceeded.1139 /// The maximum number of secrets that can be stored in a single system was exceeded.
1665 /// The length and number of secrets is limited to satisfy U.S. State Department export restrictions.1140 /// The length and number of secrets is limited to satisfy U.S. State Department export restrictions.
1666 TOO_MANY_SECRETS = 0xC0000156,1141 TOO_MANY_SECRETS = 0xC0000156,
1667
1668 /// The length of a secret exceeds the maximum allowable length.1142 /// The length of a secret exceeds the maximum allowable length.
1669 /// The length and number of secrets is limited to satisfy U.S. State Department export restrictions.1143 /// The length and number of secrets is limited to satisfy U.S. State Department export restrictions.
1670 SECRET_TOO_LONG = 0xC0000157,1144 SECRET_TOO_LONG = 0xC0000157,
1671
1672 /// The local security authority (LSA) database contains an internal inconsistency.1145 /// The local security authority (LSA) database contains an internal inconsistency.
1673 INTERNAL_DB_ERROR = 0xC0000158,1146 INTERNAL_DB_ERROR = 0xC0000158,
1674
1675 /// The requested operation cannot be performed in full-screen mode.1147 /// The requested operation cannot be performed in full-screen mode.
1676 FULLSCREEN_MODE = 0xC0000159,1148 FULLSCREEN_MODE = 0xC0000159,
1677
1678 /// During a logon attempt, the user's security context accumulated too many security IDs. This is a very unusual situation.1149 /// During a logon attempt, the user's security context accumulated too many security IDs. This is a very unusual situation.
1679 /// Remove the user from some global or local groups to reduce the number of security IDs to incorporate into the security context.1150 /// Remove the user from some global or local groups to reduce the number of security IDs to incorporate into the security context.
1680 TOO_MANY_CONTEXT_IDS = 0xC000015A,1151 TOO_MANY_CONTEXT_IDS = 0xC000015A,
1681
1682 /// A user has requested a type of logon (for example, interactive or network) that has not been granted.1152 /// A user has requested a type of logon (for example, interactive or network) that has not been granted.
1683 /// An administrator has control over who can logon interactively and through the network.1153 /// An administrator has control over who can logon interactively and through the network.
1684 LOGON_TYPE_NOT_GRANTED = 0xC000015B,1154 LOGON_TYPE_NOT_GRANTED = 0xC000015B,
1685
1686 /// The system has attempted to load or restore a file into the registry, and the specified file is not in the format of a registry file.1155 /// The system has attempted to load or restore a file into the registry, and the specified file is not in the format of a registry file.
1687 NOT_REGISTRY_FILE = 0xC000015C,1156 NOT_REGISTRY_FILE = 0xC000015C,
1688
1689 /// An attempt was made to change a user password in the security account manager without providing the necessary Windows cross-encrypted password.1157 /// An attempt was made to change a user password in the security account manager without providing the necessary Windows cross-encrypted password.
1690 NT_CROSS_ENCRYPTION_REQUIRED = 0xC000015D,1158 NT_CROSS_ENCRYPTION_REQUIRED = 0xC000015D,
1691
1692 /// A domain server has an incorrect configuration.1159 /// A domain server has an incorrect configuration.
1693 DOMAIN_CTRLR_CONFIG_ERROR = 0xC000015E,1160 DOMAIN_CTRLR_CONFIG_ERROR = 0xC000015E,
1694
1695 /// An attempt was made to explicitly access the secondary copy of information via a device control to the fault tolerance driver and the secondary copy is not present in the system.1161 /// An attempt was made to explicitly access the secondary copy of information via a device control to the fault tolerance driver and the secondary copy is not present in the system.
1696 FT_MISSING_MEMBER = 0xC000015F,1162 FT_MISSING_MEMBER = 0xC000015F,
1697
1698 /// A configuration registry node that represents a driver service entry was ill-formed and did not contain the required value entries.1163 /// A configuration registry node that represents a driver service entry was ill-formed and did not contain the required value entries.
1699 ILL_FORMED_SERVICE_ENTRY = 0xC0000160,1164 ILL_FORMED_SERVICE_ENTRY = 0xC0000160,
1700
1701 /// An illegal character was encountered.1165 /// An illegal character was encountered.
1702 /// For a multibyte character set, this includes a lead byte without a succeeding trail byte.1166 /// For a multibyte character set, this includes a lead byte without a succeeding trail byte.
1703 /// For the Unicode character set this includes the characters 0xFFFF and 0xFFFE.1167 /// For the Unicode character set this includes the characters 0xFFFF and 0xFFFE.
1704 ILLEGAL_CHARACTER = 0xC0000161,1168 ILLEGAL_CHARACTER = 0xC0000161,
1705
1706 /// No mapping for the Unicode character exists in the target multibyte code page.1169 /// No mapping for the Unicode character exists in the target multibyte code page.
1707 UNMAPPABLE_CHARACTER = 0xC0000162,1170 UNMAPPABLE_CHARACTER = 0xC0000162,
1708
1709 /// The Unicode character is not defined in the Unicode character set that is installed on the system.1171 /// The Unicode character is not defined in the Unicode character set that is installed on the system.
1710 UNDEFINED_CHARACTER = 0xC0000163,1172 UNDEFINED_CHARACTER = 0xC0000163,
1711
1712 /// The paging file cannot be created on a floppy disk.1173 /// The paging file cannot be created on a floppy disk.
1713 FLOPPY_VOLUME = 0xC0000164,1174 FLOPPY_VOLUME = 0xC0000164,
1714
1715 /// {Floppy Disk Error} While accessing a floppy disk, an ID address mark was not found.1175 /// {Floppy Disk Error} While accessing a floppy disk, an ID address mark was not found.
1716 FLOPPY_ID_MARK_NOT_FOUND = 0xC0000165,1176 FLOPPY_ID_MARK_NOT_FOUND = 0xC0000165,
1717
1718 /// {Floppy Disk Error} While accessing a floppy disk, the track address from the sector ID field was found to be different from the track address that is maintained by the controller.1177 /// {Floppy Disk Error} While accessing a floppy disk, the track address from the sector ID field was found to be different from the track address that is maintained by the controller.
1719 FLOPPY_WRONG_CYLINDER = 0xC0000166,1178 FLOPPY_WRONG_CYLINDER = 0xC0000166,
1720
1721 /// {Floppy Disk Error} The floppy disk controller reported an error that is not recognized by the floppy disk driver.1179 /// {Floppy Disk Error} The floppy disk controller reported an error that is not recognized by the floppy disk driver.
1722 FLOPPY_UNKNOWN_ERROR = 0xC0000167,1180 FLOPPY_UNKNOWN_ERROR = 0xC0000167,
1723
1724 /// {Floppy Disk Error} While accessing a floppy-disk, the controller returned inconsistent results via its registers.1181 /// {Floppy Disk Error} While accessing a floppy-disk, the controller returned inconsistent results via its registers.
1725 FLOPPY_BAD_REGISTERS = 0xC0000168,1182 FLOPPY_BAD_REGISTERS = 0xC0000168,
1726
1727 /// {Hard Disk Error} While accessing the hard disk, a recalibrate operation failed, even after retries.1183 /// {Hard Disk Error} While accessing the hard disk, a recalibrate operation failed, even after retries.
1728 DISK_RECALIBRATE_FAILED = 0xC0000169,1184 DISK_RECALIBRATE_FAILED = 0xC0000169,
1729
1730 /// {Hard Disk Error} While accessing the hard disk, a disk operation failed even after retries.1185 /// {Hard Disk Error} While accessing the hard disk, a disk operation failed even after retries.
1731 DISK_OPERATION_FAILED = 0xC000016A,1186 DISK_OPERATION_FAILED = 0xC000016A,
1732
1733 /// {Hard Disk Error} While accessing the hard disk, a disk controller reset was needed, but even that failed.1187 /// {Hard Disk Error} While accessing the hard disk, a disk controller reset was needed, but even that failed.
1734 DISK_RESET_FAILED = 0xC000016B,1188 DISK_RESET_FAILED = 0xC000016B,
1735
1736 /// An attempt was made to open a device that was sharing an interrupt request (IRQ) with other devices.1189 /// An attempt was made to open a device that was sharing an interrupt request (IRQ) with other devices.
1737 /// At least one other device that uses that IRQ was already opened.1190 /// At least one other device that uses that IRQ was already opened.
1738 /// Two concurrent opens of devices that share an IRQ and only work via interrupts is not supported for the particular bus type that the devices use.1191 /// Two concurrent opens of devices that share an IRQ and only work via interrupts is not supported for the particular bus type that the devices use.
1739 SHARED_IRQ_BUSY = 0xC000016C,1192 SHARED_IRQ_BUSY = 0xC000016C,
1740
1741 /// {FT Orphaning} A disk that is part of a fault-tolerant volume can no longer be accessed.1193 /// {FT Orphaning} A disk that is part of a fault-tolerant volume can no longer be accessed.
1742 FT_ORPHANING = 0xC000016D,1194 FT_ORPHANING = 0xC000016D,
1743
1744 /// The basic input/output system (BIOS) failed to connect a system interrupt to the device or bus for which the device is connected.1195 /// The basic input/output system (BIOS) failed to connect a system interrupt to the device or bus for which the device is connected.
1745 BIOS_FAILED_TO_CONNECT_INTERRUPT = 0xC000016E,1196 BIOS_FAILED_TO_CONNECT_INTERRUPT = 0xC000016E,
1746
1747 /// The tape could not be partitioned.1197 /// The tape could not be partitioned.
1748 PARTITION_FAILURE = 0xC0000172,1198 PARTITION_FAILURE = 0xC0000172,
1749
1750 /// When accessing a new tape of a multi-volume partition, the current blocksize is incorrect.1199 /// When accessing a new tape of a multi-volume partition, the current blocksize is incorrect.
1751 INVALID_BLOCK_LENGTH = 0xC0000173,1200 INVALID_BLOCK_LENGTH = 0xC0000173,
1752
1753 /// The tape partition information could not be found when loading a tape.1201 /// The tape partition information could not be found when loading a tape.
1754 DEVICE_NOT_PARTITIONED = 0xC0000174,1202 DEVICE_NOT_PARTITIONED = 0xC0000174,
1755
1756 /// An attempt to lock the eject media mechanism failed.1203 /// An attempt to lock the eject media mechanism failed.
1757 UNABLE_TO_LOCK_MEDIA = 0xC0000175,1204 UNABLE_TO_LOCK_MEDIA = 0xC0000175,
1758
1759 /// An attempt to unload media failed.1205 /// An attempt to unload media failed.
1760 UNABLE_TO_UNLOAD_MEDIA = 0xC0000176,1206 UNABLE_TO_UNLOAD_MEDIA = 0xC0000176,
1761
1762 /// The physical end of tape was detected.1207 /// The physical end of tape was detected.
1763 EOM_OVERFLOW = 0xC0000177,1208 EOM_OVERFLOW = 0xC0000177,
1764
1765 /// {No Media} There is no media in the drive. Insert media into drive %hs.1209 /// {No Media} There is no media in the drive. Insert media into drive %hs.
1766 NO_MEDIA = 0xC0000178,1210 NO_MEDIA = 0xC0000178,
1767
1768 /// A member could not be added to or removed from the local group because the member does not exist.1211 /// A member could not be added to or removed from the local group because the member does not exist.
1769 NO_SUCH_MEMBER = 0xC000017A,1212 NO_SUCH_MEMBER = 0xC000017A,
1770
1771 /// A new member could not be added to a local group because the member has the wrong account type.1213 /// A new member could not be added to a local group because the member has the wrong account type.
1772 INVALID_MEMBER = 0xC000017B,1214 INVALID_MEMBER = 0xC000017B,
1773
1774 /// An illegal operation was attempted on a registry key that has been marked for deletion.1215 /// An illegal operation was attempted on a registry key that has been marked for deletion.
1775 KEY_DELETED = 0xC000017C,1216 KEY_DELETED = 0xC000017C,
1776
1777 /// The system could not allocate the required space in a registry log.1217 /// The system could not allocate the required space in a registry log.
1778 NO_LOG_SPACE = 0xC000017D,1218 NO_LOG_SPACE = 0xC000017D,
1779
1780 /// Too many SIDs have been specified.1219 /// Too many SIDs have been specified.
1781 TOO_MANY_SIDS = 0xC000017E,1220 TOO_MANY_SIDS = 0xC000017E,
1782
1783 /// An attempt was made to change a user password in the security account manager without providing the necessary LM cross-encrypted password.1221 /// An attempt was made to change a user password in the security account manager without providing the necessary LM cross-encrypted password.
1784 LM_CROSS_ENCRYPTION_REQUIRED = 0xC000017F,1222 LM_CROSS_ENCRYPTION_REQUIRED = 0xC000017F,
1785
1786 /// An attempt was made to create a symbolic link in a registry key that already has subkeys or values.1223 /// An attempt was made to create a symbolic link in a registry key that already has subkeys or values.
1787 KEY_HAS_CHILDREN = 0xC0000180,1224 KEY_HAS_CHILDREN = 0xC0000180,
1788
1789 /// An attempt was made to create a stable subkey under a volatile parent key.1225 /// An attempt was made to create a stable subkey under a volatile parent key.
1790 CHILD_MUST_BE_VOLATILE = 0xC0000181,1226 CHILD_MUST_BE_VOLATILE = 0xC0000181,
1791
1792 /// The I/O device is configured incorrectly or the configuration parameters to the driver are incorrect.1227 /// The I/O device is configured incorrectly or the configuration parameters to the driver are incorrect.
1793 DEVICE_CONFIGURATION_ERROR = 0xC0000182,1228 DEVICE_CONFIGURATION_ERROR = 0xC0000182,
1794
1795 /// An error was detected between two drivers or within an I/O driver.1229 /// An error was detected between two drivers or within an I/O driver.
1796 DRIVER_INTERNAL_ERROR = 0xC0000183,1230 DRIVER_INTERNAL_ERROR = 0xC0000183,
1797
1798 /// The device is not in a valid state to perform this request.1231 /// The device is not in a valid state to perform this request.
1799 INVALID_DEVICE_STATE = 0xC0000184,1232 INVALID_DEVICE_STATE = 0xC0000184,
1800
1801 /// The I/O device reported an I/O error.1233 /// The I/O device reported an I/O error.
1802 IO_DEVICE_ERROR = 0xC0000185,1234 IO_DEVICE_ERROR = 0xC0000185,
1803
1804 /// A protocol error was detected between the driver and the device.1235 /// A protocol error was detected between the driver and the device.
1805 DEVICE_PROTOCOL_ERROR = 0xC0000186,1236 DEVICE_PROTOCOL_ERROR = 0xC0000186,
1806
1807 /// This operation is only allowed for the primary domain controller of the domain.1237 /// This operation is only allowed for the primary domain controller of the domain.
1808 BACKUP_CONTROLLER = 0xC0000187,1238 BACKUP_CONTROLLER = 0xC0000187,
1809
1810 /// The log file space is insufficient to support this operation.1239 /// The log file space is insufficient to support this operation.
1811 LOG_FILE_FULL = 0xC0000188,1240 LOG_FILE_FULL = 0xC0000188,
1812
1813 /// A write operation was attempted to a volume after it was dismounted.1241 /// A write operation was attempted to a volume after it was dismounted.
1814 TOO_LATE = 0xC0000189,1242 TOO_LATE = 0xC0000189,
1815
1816 /// The workstation does not have a trust secret for the primary domain in the local LSA database.1243 /// The workstation does not have a trust secret for the primary domain in the local LSA database.
1817 NO_TRUST_LSA_SECRET = 0xC000018A,1244 NO_TRUST_LSA_SECRET = 0xC000018A,
1818
1819 /// On applicable Windows Server releases, the SAM database does not have a computer account for this workstation trust relationship.1245 /// On applicable Windows Server releases, the SAM database does not have a computer account for this workstation trust relationship.
1820 NO_TRUST_SAM_ACCOUNT = 0xC000018B,1246 NO_TRUST_SAM_ACCOUNT = 0xC000018B,
1821
1822 /// The logon request failed because the trust relationship between the primary domain and the trusted domain failed.1247 /// The logon request failed because the trust relationship between the primary domain and the trusted domain failed.
1823 TRUSTED_DOMAIN_FAILURE = 0xC000018C,1248 TRUSTED_DOMAIN_FAILURE = 0xC000018C,
1824
1825 /// The logon request failed because the trust relationship between this workstation and the primary domain failed.1249 /// The logon request failed because the trust relationship between this workstation and the primary domain failed.
1826 TRUSTED_RELATIONSHIP_FAILURE = 0xC000018D,1250 TRUSTED_RELATIONSHIP_FAILURE = 0xC000018D,
1827
1828 /// The Eventlog log file is corrupt.1251 /// The Eventlog log file is corrupt.
1829 EVENTLOG_FILE_CORRUPT = 0xC000018E,1252 EVENTLOG_FILE_CORRUPT = 0xC000018E,
1830
1831 /// No Eventlog log file could be opened. The Eventlog service did not start.1253 /// No Eventlog log file could be opened. The Eventlog service did not start.
1832 EVENTLOG_CANT_START = 0xC000018F,1254 EVENTLOG_CANT_START = 0xC000018F,
1833
1834 /// The network logon failed. This might be because the validation authority cannot be reached.1255 /// The network logon failed. This might be because the validation authority cannot be reached.
1835 TRUST_FAILURE = 0xC0000190,1256 TRUST_FAILURE = 0xC0000190,
1836
1837 /// An attempt was made to acquire a mutant such that its maximum count would have been exceeded.1257 /// An attempt was made to acquire a mutant such that its maximum count would have been exceeded.
1838 MUTANT_LIMIT_EXCEEDED = 0xC0000191,1258 MUTANT_LIMIT_EXCEEDED = 0xC0000191,
1839
1840 /// An attempt was made to logon, but the NetLogon service was not started.1259 /// An attempt was made to logon, but the NetLogon service was not started.
1841 NETLOGON_NOT_STARTED = 0xC0000192,1260 NETLOGON_NOT_STARTED = 0xC0000192,
1842
1843 /// The user account has expired.1261 /// The user account has expired.
1844 ACCOUNT_EXPIRED = 0xC0000193,1262 ACCOUNT_EXPIRED = 0xC0000193,
1845
1846 /// {EXCEPTION} Possible deadlock condition.1263 /// {EXCEPTION} Possible deadlock condition.
1847 POSSIBLE_DEADLOCK = 0xC0000194,1264 POSSIBLE_DEADLOCK = 0xC0000194,
1848
1849 /// Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed.1265 /// Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed.
1850 /// Disconnect all previous connections to the server or shared resource and try again.1266 /// Disconnect all previous connections to the server or shared resource and try again.
1851 NETWORK_CREDENTIAL_CONFLICT = 0xC0000195,1267 NETWORK_CREDENTIAL_CONFLICT = 0xC0000195,
1852
1853 /// An attempt was made to establish a session to a network server, but there are already too many sessions established to that server.1268 /// An attempt was made to establish a session to a network server, but there are already too many sessions established to that server.
1854 REMOTE_SESSION_LIMIT = 0xC0000196,1269 REMOTE_SESSION_LIMIT = 0xC0000196,
1855
1856 /// The log file has changed between reads.1270 /// The log file has changed between reads.
1857 EVENTLOG_FILE_CHANGED = 0xC0000197,1271 EVENTLOG_FILE_CHANGED = 0xC0000197,
1858
1859 /// The account used is an interdomain trust account.1272 /// The account used is an interdomain trust account.
1860 /// Use your global user account or local user account to access this server.1273 /// Use your global user account or local user account to access this server.
1861 NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = 0xC0000198,1274 NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = 0xC0000198,
1862
1863 /// The account used is a computer account.1275 /// The account used is a computer account.
1864 /// Use your global user account or local user account to access this server.1276 /// Use your global user account or local user account to access this server.
1865 NOLOGON_WORKSTATION_TRUST_ACCOUNT = 0xC0000199,1277 NOLOGON_WORKSTATION_TRUST_ACCOUNT = 0xC0000199,
1866
1867 /// The account used is a server trust account.1278 /// The account used is a server trust account.
1868 /// Use your global user account or local user account to access this server.1279 /// Use your global user account or local user account to access this server.
1869 NOLOGON_SERVER_TRUST_ACCOUNT = 0xC000019A,1280 NOLOGON_SERVER_TRUST_ACCOUNT = 0xC000019A,
1870
1871 /// The name or SID of the specified domain is inconsistent with the trust information for that domain.1281 /// The name or SID of the specified domain is inconsistent with the trust information for that domain.
1872 DOMAIN_TRUST_INCONSISTENT = 0xC000019B,1282 DOMAIN_TRUST_INCONSISTENT = 0xC000019B,
1873
1874 /// A volume has been accessed for which a file system driver is required that has not yet been loaded.1283 /// A volume has been accessed for which a file system driver is required that has not yet been loaded.
1875 FS_DRIVER_REQUIRED = 0xC000019C,1284 FS_DRIVER_REQUIRED = 0xC000019C,
1876
1877 /// Indicates that the specified image is already loaded as a DLL.1285 /// Indicates that the specified image is already loaded as a DLL.
1878 IMAGE_ALREADY_LOADED_AS_DLL = 0xC000019D,1286 IMAGE_ALREADY_LOADED_AS_DLL = 0xC000019D,
1879
1880 /// Short name settings cannot be changed on this volume due to the global registry setting.1287 /// Short name settings cannot be changed on this volume due to the global registry setting.
1881 INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING = 0xC000019E,1288 INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING = 0xC000019E,
1882
1883 /// Short names are not enabled on this volume.1289 /// Short names are not enabled on this volume.
1884 SHORT_NAMES_NOT_ENABLED_ON_VOLUME = 0xC000019F,1290 SHORT_NAMES_NOT_ENABLED_ON_VOLUME = 0xC000019F,
1885
1886 /// The security stream for the given volume is in an inconsistent state. Please run CHKDSK on the volume.1291 /// The security stream for the given volume is in an inconsistent state. Please run CHKDSK on the volume.
1887 SECURITY_STREAM_IS_INCONSISTENT = 0xC00001A0,1292 SECURITY_STREAM_IS_INCONSISTENT = 0xC00001A0,
1888
1889 /// A requested file lock operation cannot be processed due to an invalid byte range.1293 /// A requested file lock operation cannot be processed due to an invalid byte range.
1890 INVALID_LOCK_RANGE = 0xC00001A1,1294 INVALID_LOCK_RANGE = 0xC00001A1,
1891
1892 /// The specified access control entry (ACE) contains an invalid condition.1295 /// The specified access control entry (ACE) contains an invalid condition.
1893 INVALID_ACE_CONDITION = 0xC00001A2,1296 INVALID_ACE_CONDITION = 0xC00001A2,
1894
1895 /// The subsystem needed to support the image type is not present.1297 /// The subsystem needed to support the image type is not present.
1896 IMAGE_SUBSYSTEM_NOT_PRESENT = 0xC00001A3,1298 IMAGE_SUBSYSTEM_NOT_PRESENT = 0xC00001A3,
1897
1898 /// The specified file already has a notification GUID associated with it.1299 /// The specified file already has a notification GUID associated with it.
1899 NOTIFICATION_GUID_ALREADY_DEFINED = 0xC00001A4,1300 NOTIFICATION_GUID_ALREADY_DEFINED = 0xC00001A4,
1900
1901 /// A remote open failed because the network open restrictions were not satisfied.1301 /// A remote open failed because the network open restrictions were not satisfied.
1902 NETWORK_OPEN_RESTRICTION = 0xC0000201,1302 NETWORK_OPEN_RESTRICTION = 0xC0000201,
1903
1904 /// There is no user session key for the specified logon session.1303 /// There is no user session key for the specified logon session.
1905 NO_USER_SESSION_KEY = 0xC0000202,1304 NO_USER_SESSION_KEY = 0xC0000202,
1906
1907 /// The remote user session has been deleted.1305 /// The remote user session has been deleted.
1908 USER_SESSION_DELETED = 0xC0000203,1306 USER_SESSION_DELETED = 0xC0000203,
1909
1910 /// Indicates the specified resource language ID cannot be found in the image file.1307 /// Indicates the specified resource language ID cannot be found in the image file.
1911 RESOURCE_LANG_NOT_FOUND = 0xC0000204,1308 RESOURCE_LANG_NOT_FOUND = 0xC0000204,
1912
1913 /// Insufficient server resources exist to complete the request.1309 /// Insufficient server resources exist to complete the request.
1914 INSUFF_SERVER_RESOURCES = 0xC0000205,1310 INSUFF_SERVER_RESOURCES = 0xC0000205,
1915
1916 /// The size of the buffer is invalid for the specified operation.1311 /// The size of the buffer is invalid for the specified operation.
1917 INVALID_BUFFER_SIZE = 0xC0000206,1312 INVALID_BUFFER_SIZE = 0xC0000206,
1918
1919 /// The transport rejected the specified network address as invalid.1313 /// The transport rejected the specified network address as invalid.
1920 INVALID_ADDRESS_COMPONENT = 0xC0000207,1314 INVALID_ADDRESS_COMPONENT = 0xC0000207,
1921
1922 /// The transport rejected the specified network address due to invalid use of a wildcard.1315 /// The transport rejected the specified network address due to invalid use of a wildcard.
1923 INVALID_ADDRESS_WILDCARD = 0xC0000208,1316 INVALID_ADDRESS_WILDCARD = 0xC0000208,
1924
1925 /// The transport address could not be opened because all the available addresses are in use.1317 /// The transport address could not be opened because all the available addresses are in use.
1926 TOO_MANY_ADDRESSES = 0xC0000209,1318 TOO_MANY_ADDRESSES = 0xC0000209,
1927
1928 /// The transport address could not be opened because it already exists.1319 /// The transport address could not be opened because it already exists.
1929 ADDRESS_ALREADY_EXISTS = 0xC000020A,1320 ADDRESS_ALREADY_EXISTS = 0xC000020A,
1930
1931 /// The transport address is now closed.1321 /// The transport address is now closed.
1932 ADDRESS_CLOSED = 0xC000020B,1322 ADDRESS_CLOSED = 0xC000020B,
1933
1934 /// The transport connection is now disconnected.1323 /// The transport connection is now disconnected.
1935 CONNECTION_DISCONNECTED = 0xC000020C,1324 CONNECTION_DISCONNECTED = 0xC000020C,
1936
1937 /// The transport connection has been reset.1325 /// The transport connection has been reset.
1938 CONNECTION_RESET = 0xC000020D,1326 CONNECTION_RESET = 0xC000020D,
1939
1940 /// The transport cannot dynamically acquire any more nodes.1327 /// The transport cannot dynamically acquire any more nodes.
1941 TOO_MANY_NODES = 0xC000020E,1328 TOO_MANY_NODES = 0xC000020E,
1942
1943 /// The transport aborted a pending transaction.1329 /// The transport aborted a pending transaction.
1944 TRANSACTION_ABORTED = 0xC000020F,1330 TRANSACTION_ABORTED = 0xC000020F,
1945
1946 /// The transport timed out a request that is waiting for a response.1331 /// The transport timed out a request that is waiting for a response.
1947 TRANSACTION_TIMED_OUT = 0xC0000210,1332 TRANSACTION_TIMED_OUT = 0xC0000210,
1948
1949 /// The transport did not receive a release for a pending response.1333 /// The transport did not receive a release for a pending response.
1950 TRANSACTION_NO_RELEASE = 0xC0000211,1334 TRANSACTION_NO_RELEASE = 0xC0000211,
1951
1952 /// The transport did not find a transaction that matches the specific token.1335 /// The transport did not find a transaction that matches the specific token.
1953 TRANSACTION_NO_MATCH = 0xC0000212,1336 TRANSACTION_NO_MATCH = 0xC0000212,
1954
1955 /// The transport had previously responded to a transaction request.1337 /// The transport had previously responded to a transaction request.
1956 TRANSACTION_RESPONDED = 0xC0000213,1338 TRANSACTION_RESPONDED = 0xC0000213,
1957
1958 /// The transport does not recognize the specified transaction request ID.1339 /// The transport does not recognize the specified transaction request ID.
1959 TRANSACTION_INVALID_ID = 0xC0000214,1340 TRANSACTION_INVALID_ID = 0xC0000214,
1960
1961 /// The transport does not recognize the specified transaction request type.1341 /// The transport does not recognize the specified transaction request type.
1962 TRANSACTION_INVALID_TYPE = 0xC0000215,1342 TRANSACTION_INVALID_TYPE = 0xC0000215,
1963
1964 /// The transport can only process the specified request on the server side of a session.1343 /// The transport can only process the specified request on the server side of a session.
1965 NOT_SERVER_SESSION = 0xC0000216,1344 NOT_SERVER_SESSION = 0xC0000216,
1966
1967 /// The transport can only process the specified request on the client side of a session.1345 /// The transport can only process the specified request on the client side of a session.
1968 NOT_CLIENT_SESSION = 0xC0000217,1346 NOT_CLIENT_SESSION = 0xC0000217,
1969
1970 /// {Registry File Failure} The registry cannot load the hive (file): %hs or its log or alternate. It is corrupt, absent, or not writable.1347 /// {Registry File Failure} The registry cannot load the hive (file): %hs or its log or alternate. It is corrupt, absent, or not writable.
1971 CANNOT_LOAD_REGISTRY_FILE = 0xC0000218,1348 CANNOT_LOAD_REGISTRY_FILE = 0xC0000218,
1972
1973 /// {Unexpected Failure in DebugActiveProcess} An unexpected failure occurred while processing a DebugActiveProcess API request.1349 /// {Unexpected Failure in DebugActiveProcess} An unexpected failure occurred while processing a DebugActiveProcess API request.
1974 /// Choosing OK will terminate the process, and choosing Cancel will ignore the error.1350 /// Choosing OK will terminate the process, and choosing Cancel will ignore the error.
1975 DEBUG_ATTACH_FAILED = 0xC0000219,1351 DEBUG_ATTACH_FAILED = 0xC0000219,
1976
1977 /// {Fatal System Error} The %hs system process terminated unexpectedly with a status of 0x%08x (0x%08x 0x%08x). The system has been shut down.1352 /// {Fatal System Error} The %hs system process terminated unexpectedly with a status of 0x%08x (0x%08x 0x%08x). The system has been shut down.
1978 SYSTEM_PROCESS_TERMINATED = 0xC000021A,1353 SYSTEM_PROCESS_TERMINATED = 0xC000021A,
1979
1980 /// {Data Not Accepted} The TDI client could not handle the data received during an indication.1354 /// {Data Not Accepted} The TDI client could not handle the data received during an indication.
1981 DATA_NOT_ACCEPTED = 0xC000021B,1355 DATA_NOT_ACCEPTED = 0xC000021B,
1982
1983 /// {Unable to Retrieve Browser Server List} The list of servers for this workgroup is not currently available.1356 /// {Unable to Retrieve Browser Server List} The list of servers for this workgroup is not currently available.
1984 NO_BROWSER_SERVERS_FOUND = 0xC000021C,1357 NO_BROWSER_SERVERS_FOUND = 0xC000021C,
1985
1986 /// NTVDM encountered a hard error.1358 /// NTVDM encountered a hard error.
1987 VDM_HARD_ERROR = 0xC000021D,1359 VDM_HARD_ERROR = 0xC000021D,
1988
1989 /// {Cancel Timeout} The driver %hs failed to complete a canceled I/O request in the allotted time.1360 /// {Cancel Timeout} The driver %hs failed to complete a canceled I/O request in the allotted time.
1990 DRIVER_CANCEL_TIMEOUT = 0xC000021E,1361 DRIVER_CANCEL_TIMEOUT = 0xC000021E,
1991
1992 /// {Reply Message Mismatch} An attempt was made to reply to an LPC message, but the thread specified by the client ID in the message was not waiting on that message.1362 /// {Reply Message Mismatch} An attempt was made to reply to an LPC message, but the thread specified by the client ID in the message was not waiting on that message.
1993 REPLY_MESSAGE_MISMATCH = 0xC000021F,1363 REPLY_MESSAGE_MISMATCH = 0xC000021F,
1994
1995 /// {Mapped View Alignment Incorrect} An attempt was made to map a view of a file, but either the specified base address or the offset into the file were not aligned on the proper allocation granularity.1364 /// {Mapped View Alignment Incorrect} An attempt was made to map a view of a file, but either the specified base address or the offset into the file were not aligned on the proper allocation granularity.
1996 MAPPED_ALIGNMENT = 0xC0000220,1365 MAPPED_ALIGNMENT = 0xC0000220,
1997
1998 /// {Bad Image Checksum} The image %hs is possibly corrupt.1366 /// {Bad Image Checksum} The image %hs is possibly corrupt.
1999 /// The header checksum does not match the computed checksum.1367 /// The header checksum does not match the computed checksum.
2000 IMAGE_CHECKSUM_MISMATCH = 0xC0000221,1368 IMAGE_CHECKSUM_MISMATCH = 0xC0000221,
2001
2002 /// {Delayed Write Failed} Windows was unable to save all the data for the file %hs. The data has been lost.1369 /// {Delayed Write Failed} Windows was unable to save all the data for the file %hs. The data has been lost.
2003 /// This error might be caused by a failure of your computer hardware or network connection. Try to save this file elsewhere.1370 /// This error might be caused by a failure of your computer hardware or network connection. Try to save this file elsewhere.
2004 LOST_WRITEBEHIND_DATA = 0xC0000222,1371 LOST_WRITEBEHIND_DATA = 0xC0000222,
2005
2006 /// The parameters passed to the server in the client/server shared memory window were invalid.1372 /// The parameters passed to the server in the client/server shared memory window were invalid.
2007 /// Too much data might have been put in the shared memory window.1373 /// Too much data might have been put in the shared memory window.
2008 CLIENT_SERVER_PARAMETERS_INVALID = 0xC0000223,1374 CLIENT_SERVER_PARAMETERS_INVALID = 0xC0000223,
2009
2010 /// The user password must be changed before logging on the first time.1375 /// The user password must be changed before logging on the first time.
2011 PASSWORD_MUST_CHANGE = 0xC0000224,1376 PASSWORD_MUST_CHANGE = 0xC0000224,
2012
2013 /// The object was not found.1377 /// The object was not found.
2014 NOT_FOUND = 0xC0000225,1378 NOT_FOUND = 0xC0000225,
2015
2016 /// The stream is not a tiny stream.1379 /// The stream is not a tiny stream.
2017 NOT_TINY_STREAM = 0xC0000226,1380 NOT_TINY_STREAM = 0xC0000226,
2018
2019 /// A transaction recovery failed.1381 /// A transaction recovery failed.
2020 RECOVERY_FAILURE = 0xC0000227,1382 RECOVERY_FAILURE = 0xC0000227,
2021
2022 /// The request must be handled by the stack overflow code.1383 /// The request must be handled by the stack overflow code.
2023 STACK_OVERFLOW_READ = 0xC0000228,1384 STACK_OVERFLOW_READ = 0xC0000228,
2024
2025 /// A consistency check failed.1385 /// A consistency check failed.
2026 FAIL_CHECK = 0xC0000229,1386 FAIL_CHECK = 0xC0000229,
2027
2028 /// The attempt to insert the ID in the index failed because the ID is already in the index.1387 /// The attempt to insert the ID in the index failed because the ID is already in the index.
2029 DUPLICATE_OBJECTID = 0xC000022A,1388 DUPLICATE_OBJECTID = 0xC000022A,
2030
2031 /// The attempt to set the object ID failed because the object already has an ID.1389 /// The attempt to set the object ID failed because the object already has an ID.
2032 OBJECTID_EXISTS = 0xC000022B,1390 OBJECTID_EXISTS = 0xC000022B,
2033
2034 /// Internal OFS status codes indicating how an allocation operation is handled.1391 /// Internal OFS status codes indicating how an allocation operation is handled.
2035 /// Either it is retried after the containing oNode is moved or the extent stream is converted to a large stream.1392 /// Either it is retried after the containing oNode is moved or the extent stream is converted to a large stream.
2036 CONVERT_TO_LARGE = 0xC000022C,1393 CONVERT_TO_LARGE = 0xC000022C,
2037
2038 /// The request needs to be retried.1394 /// The request needs to be retried.
2039 RETRY = 0xC000022D,1395 RETRY = 0xC000022D,
2040
2041 /// The attempt to find the object found an object on the volume that matches by ID; however, it is out of the scope of the handle that is used for the operation.1396 /// The attempt to find the object found an object on the volume that matches by ID; however, it is out of the scope of the handle that is used for the operation.
2042 FOUND_OUT_OF_SCOPE = 0xC000022E,1397 FOUND_OUT_OF_SCOPE = 0xC000022E,
2043
2044 /// The bucket array must be grown. Retry the transaction after doing so.1398 /// The bucket array must be grown. Retry the transaction after doing so.
2045 ALLOCATE_BUCKET = 0xC000022F,1399 ALLOCATE_BUCKET = 0xC000022F,
2046
2047 /// The specified property set does not exist on the object.1400 /// The specified property set does not exist on the object.
2048 PROPSET_NOT_FOUND = 0xC0000230,1401 PROPSET_NOT_FOUND = 0xC0000230,
2049
2050 /// The user/kernel marshaling buffer has overflowed.1402 /// The user/kernel marshaling buffer has overflowed.
2051 MARSHALL_OVERFLOW = 0xC0000231,1403 MARSHALL_OVERFLOW = 0xC0000231,
2052
2053 /// The supplied variant structure contains invalid data.1404 /// The supplied variant structure contains invalid data.
2054 INVALID_VARIANT = 0xC0000232,1405 INVALID_VARIANT = 0xC0000232,
2055
2056 /// A domain controller for this domain was not found.1406 /// A domain controller for this domain was not found.
2057 DOMAIN_CONTROLLER_NOT_FOUND = 0xC0000233,1407 DOMAIN_CONTROLLER_NOT_FOUND = 0xC0000233,
2058
2059 /// The user account has been automatically locked because too many invalid logon attempts or password change attempts have been requested.1408 /// The user account has been automatically locked because too many invalid logon attempts or password change attempts have been requested.
2060 ACCOUNT_LOCKED_OUT = 0xC0000234,1409 ACCOUNT_LOCKED_OUT = 0xC0000234,
2061
2062 /// NtClose was called on a handle that was protected from close via NtSetInformationObject.1410 /// NtClose was called on a handle that was protected from close via NtSetInformationObject.
2063 HANDLE_NOT_CLOSABLE = 0xC0000235,1411 HANDLE_NOT_CLOSABLE = 0xC0000235,
2064
2065 /// The transport-connection attempt was refused by the remote system.1412 /// The transport-connection attempt was refused by the remote system.
2066 CONNECTION_REFUSED = 0xC0000236,1413 CONNECTION_REFUSED = 0xC0000236,
2067
2068 /// The transport connection was gracefully closed.1414 /// The transport connection was gracefully closed.
2069 GRACEFUL_DISCONNECT = 0xC0000237,1415 GRACEFUL_DISCONNECT = 0xC0000237,
2070
2071 /// The transport endpoint already has an address associated with it.1416 /// The transport endpoint already has an address associated with it.
2072 ADDRESS_ALREADY_ASSOCIATED = 0xC0000238,1417 ADDRESS_ALREADY_ASSOCIATED = 0xC0000238,
2073
2074 /// An address has not yet been associated with the transport endpoint.1418 /// An address has not yet been associated with the transport endpoint.
2075 ADDRESS_NOT_ASSOCIATED = 0xC0000239,1419 ADDRESS_NOT_ASSOCIATED = 0xC0000239,
2076
2077 /// An operation was attempted on a nonexistent transport connection.1420 /// An operation was attempted on a nonexistent transport connection.
2078 CONNECTION_INVALID = 0xC000023A,1421 CONNECTION_INVALID = 0xC000023A,
2079
2080 /// An invalid operation was attempted on an active transport connection.1422 /// An invalid operation was attempted on an active transport connection.
2081 CONNECTION_ACTIVE = 0xC000023B,1423 CONNECTION_ACTIVE = 0xC000023B,
2082
2083 /// The remote network is not reachable by the transport.1424 /// The remote network is not reachable by the transport.
2084 NETWORK_UNREACHABLE = 0xC000023C,1425 NETWORK_UNREACHABLE = 0xC000023C,
2085
2086 /// The remote system is not reachable by the transport.1426 /// The remote system is not reachable by the transport.
2087 HOST_UNREACHABLE = 0xC000023D,1427 HOST_UNREACHABLE = 0xC000023D,
2088
2089 /// The remote system does not support the transport protocol.1428 /// The remote system does not support the transport protocol.
2090 PROTOCOL_UNREACHABLE = 0xC000023E,1429 PROTOCOL_UNREACHABLE = 0xC000023E,
2091
2092 /// No service is operating at the destination port of the transport on the remote system.1430 /// No service is operating at the destination port of the transport on the remote system.
2093 PORT_UNREACHABLE = 0xC000023F,1431 PORT_UNREACHABLE = 0xC000023F,
2094
2095 /// The request was aborted.1432 /// The request was aborted.
2096 REQUEST_ABORTED = 0xC0000240,1433 REQUEST_ABORTED = 0xC0000240,
2097
2098 /// The transport connection was aborted by the local system.1434 /// The transport connection was aborted by the local system.
2099 CONNECTION_ABORTED = 0xC0000241,1435 CONNECTION_ABORTED = 0xC0000241,
2100
2101 /// The specified buffer contains ill-formed data.1436 /// The specified buffer contains ill-formed data.
2102 BAD_COMPRESSION_BUFFER = 0xC0000242,1437 BAD_COMPRESSION_BUFFER = 0xC0000242,
2103
2104 /// The requested operation cannot be performed on a file with a user mapped section open.1438 /// The requested operation cannot be performed on a file with a user mapped section open.
2105 USER_MAPPED_FILE = 0xC0000243,1439 USER_MAPPED_FILE = 0xC0000243,
2106
2107 /// {Audit Failed} An attempt to generate a security audit failed.1440 /// {Audit Failed} An attempt to generate a security audit failed.
2108 AUDIT_FAILED = 0xC0000244,1441 AUDIT_FAILED = 0xC0000244,
2109
2110 /// The timer resolution was not previously set by the current process.1442 /// The timer resolution was not previously set by the current process.
2111 TIMER_RESOLUTION_NOT_SET = 0xC0000245,1443 TIMER_RESOLUTION_NOT_SET = 0xC0000245,
2112
2113 /// A connection to the server could not be made because the limit on the number of concurrent connections for this account has been reached.1444 /// A connection to the server could not be made because the limit on the number of concurrent connections for this account has been reached.
2114 CONNECTION_COUNT_LIMIT = 0xC0000246,1445 CONNECTION_COUNT_LIMIT = 0xC0000246,
2115
2116 /// Attempting to log on during an unauthorized time of day for this account.1446 /// Attempting to log on during an unauthorized time of day for this account.
2117 LOGIN_TIME_RESTRICTION = 0xC0000247,1447 LOGIN_TIME_RESTRICTION = 0xC0000247,
2118
2119 /// The account is not authorized to log on from this station.1448 /// The account is not authorized to log on from this station.
2120 LOGIN_WKSTA_RESTRICTION = 0xC0000248,1449 LOGIN_WKSTA_RESTRICTION = 0xC0000248,
2121
2122 /// {UP/MP Image Mismatch} The image %hs has been modified for use on a uniprocessor system, but you are running it on a multiprocessor machine. Reinstall the image file.1450 /// {UP/MP Image Mismatch} The image %hs has been modified for use on a uniprocessor system, but you are running it on a multiprocessor machine. Reinstall the image file.
2123 IMAGE_MP_UP_MISMATCH = 0xC0000249,1451 IMAGE_MP_UP_MISMATCH = 0xC0000249,
2124
2125 /// There is insufficient account information to log you on.1452 /// There is insufficient account information to log you on.
2126 INSUFFICIENT_LOGON_INFO = 0xC0000250,1453 INSUFFICIENT_LOGON_INFO = 0xC0000250,
2127
2128 /// {Invalid DLL Entrypoint} The dynamic link library %hs is not written correctly.1454 /// {Invalid DLL Entrypoint} The dynamic link library %hs is not written correctly.
2129 /// The stack pointer has been left in an inconsistent state.1455 /// The stack pointer has been left in an inconsistent state.
2130 /// The entry point should be declared as WINAPI or STDCALL.1456 /// The entry point should be declared as WINAPI or STDCALL.
2131 /// Select YES to fail the DLL load. Select NO to continue execution.1457 /// Select YES to fail the DLL load. Select NO to continue execution.
2132 /// Selecting NO might cause the application to operate incorrectly.1458 /// Selecting NO might cause the application to operate incorrectly.
2133 BAD_DLL_ENTRYPOINT = 0xC0000251,1459 BAD_DLL_ENTRYPOINT = 0xC0000251,
2134
2135 /// {Invalid Service Callback Entrypoint} The %hs service is not written correctly.1460 /// {Invalid Service Callback Entrypoint} The %hs service is not written correctly.
2136 /// The stack pointer has been left in an inconsistent state.1461 /// The stack pointer has been left in an inconsistent state.
2137 /// The callback entry point should be declared as WINAPI or STDCALL.1462 /// The callback entry point should be declared as WINAPI or STDCALL.
2138 /// Selecting OK will cause the service to continue operation.1463 /// Selecting OK will cause the service to continue operation.
2139 /// However, the service process might operate incorrectly.1464 /// However, the service process might operate incorrectly.
2140 BAD_SERVICE_ENTRYPOINT = 0xC0000252,1465 BAD_SERVICE_ENTRYPOINT = 0xC0000252,
2141
2142 /// The server received the messages but did not send a reply.1466 /// The server received the messages but did not send a reply.
2143 LPC_REPLY_LOST = 0xC0000253,1467 LPC_REPLY_LOST = 0xC0000253,
2144
2145 /// There is an IP address conflict with another system on the network.1468 /// There is an IP address conflict with another system on the network.
2146 IP_ADDRESS_CONFLICT1 = 0xC0000254,1469 IP_ADDRESS_CONFLICT1 = 0xC0000254,
2147
2148 /// There is an IP address conflict with another system on the network.1470 /// There is an IP address conflict with another system on the network.
2149 IP_ADDRESS_CONFLICT2 = 0xC0000255,1471 IP_ADDRESS_CONFLICT2 = 0xC0000255,
2150
2151 /// {Low On Registry Space} The system has reached the maximum size that is allowed for the system part of the registry. Additional storage requests will be ignored.1472 /// {Low On Registry Space} The system has reached the maximum size that is allowed for the system part of the registry. Additional storage requests will be ignored.
2152 REGISTRY_QUOTA_LIMIT = 0xC0000256,1473 REGISTRY_QUOTA_LIMIT = 0xC0000256,
2153
2154 /// The contacted server does not support the indicated part of the DFS namespace.1474 /// The contacted server does not support the indicated part of the DFS namespace.
2155 PATH_NOT_COVERED = 0xC0000257,1475 PATH_NOT_COVERED = 0xC0000257,
2156
2157 /// A callback return system service cannot be executed when no callback is active.1476 /// A callback return system service cannot be executed when no callback is active.
2158 NO_CALLBACK_ACTIVE = 0xC0000258,1477 NO_CALLBACK_ACTIVE = 0xC0000258,
2159
2160 /// The service being accessed is licensed for a particular number of connections.1478 /// The service being accessed is licensed for a particular number of connections.
2161 /// No more connections can be made to the service at this time because the service has already accepted the maximum number of connections.1479 /// No more connections can be made to the service at this time because the service has already accepted the maximum number of connections.
2162 LICENSE_QUOTA_EXCEEDED = 0xC0000259,1480 LICENSE_QUOTA_EXCEEDED = 0xC0000259,
2163
2164 /// The password provided is too short to meet the policy of your user account. Choose a longer password.1481 /// The password provided is too short to meet the policy of your user account. Choose a longer password.
2165 PWD_TOO_SHORT = 0xC000025A,1482 PWD_TOO_SHORT = 0xC000025A,
2166
2167 /// The policy of your user account does not allow you to change passwords too frequently.1483 /// The policy of your user account does not allow you to change passwords too frequently.
2168 /// This is done to prevent users from changing back to a familiar, but potentially discovered, password.1484 /// This is done to prevent users from changing back to a familiar, but potentially discovered, password.
2169 /// If you feel your password has been compromised, contact your administrator immediately to have a new one assigned.1485 /// If you feel your password has been compromised, contact your administrator immediately to have a new one assigned.
2170 PWD_TOO_RECENT = 0xC000025B,1486 PWD_TOO_RECENT = 0xC000025B,
2171
2172 /// You have attempted to change your password to one that you have used in the past.1487 /// You have attempted to change your password to one that you have used in the past.
2173 /// The policy of your user account does not allow this.1488 /// The policy of your user account does not allow this.
2174 /// Select a password that you have not previously used.1489 /// Select a password that you have not previously used.
2175 PWD_HISTORY_CONFLICT = 0xC000025C,1490 PWD_HISTORY_CONFLICT = 0xC000025C,
2176
2177 /// You have attempted to load a legacy device driver while its device instance had been disabled.1491 /// You have attempted to load a legacy device driver while its device instance had been disabled.
2178 PLUGPLAY_NO_DEVICE = 0xC000025E,1492 PLUGPLAY_NO_DEVICE = 0xC000025E,
2179
2180 /// The specified compression format is unsupported.1493 /// The specified compression format is unsupported.
2181 UNSUPPORTED_COMPRESSION = 0xC000025F,1494 UNSUPPORTED_COMPRESSION = 0xC000025F,
2182
2183 /// The specified hardware profile configuration is invalid.1495 /// The specified hardware profile configuration is invalid.
2184 INVALID_HW_PROFILE = 0xC0000260,1496 INVALID_HW_PROFILE = 0xC0000260,
2185
2186 /// The specified Plug and Play registry device path is invalid.1497 /// The specified Plug and Play registry device path is invalid.
2187 INVALID_PLUGPLAY_DEVICE_PATH = 0xC0000261,1498 INVALID_PLUGPLAY_DEVICE_PATH = 0xC0000261,
2188
2189 /// {Driver Entry Point Not Found} The %hs device driver could not locate the ordinal %ld in driver %hs.1499 /// {Driver Entry Point Not Found} The %hs device driver could not locate the ordinal %ld in driver %hs.
2190 DRIVER_ORDINAL_NOT_FOUND = 0xC0000262,1500 DRIVER_ORDINAL_NOT_FOUND = 0xC0000262,
2191
2192 /// {Driver Entry Point Not Found} The %hs device driver could not locate the entry point %hs in driver %hs.1501 /// {Driver Entry Point Not Found} The %hs device driver could not locate the entry point %hs in driver %hs.
2193 DRIVER_ENTRYPOINT_NOT_FOUND = 0xC0000263,1502 DRIVER_ENTRYPOINT_NOT_FOUND = 0xC0000263,
2194
2195 /// {Application Error} The application attempted to release a resource it did not own. Click OK to terminate the application.1503 /// {Application Error} The application attempted to release a resource it did not own. Click OK to terminate the application.
2196 RESOURCE_NOT_OWNED = 0xC0000264,1504 RESOURCE_NOT_OWNED = 0xC0000264,
2197
2198 /// An attempt was made to create more links on a file than the file system supports.1505 /// An attempt was made to create more links on a file than the file system supports.
2199 TOO_MANY_LINKS = 0xC0000265,1506 TOO_MANY_LINKS = 0xC0000265,
2200
2201 /// The specified quota list is internally inconsistent with its descriptor.1507 /// The specified quota list is internally inconsistent with its descriptor.
2202 QUOTA_LIST_INCONSISTENT = 0xC0000266,1508 QUOTA_LIST_INCONSISTENT = 0xC0000266,
2203
2204 /// The specified file has been relocated to offline storage.1509 /// The specified file has been relocated to offline storage.
2205 FILE_IS_OFFLINE = 0xC0000267,1510 FILE_IS_OFFLINE = 0xC0000267,
2206
2207 /// {Windows Evaluation Notification} The evaluation period for this installation of Windows has expired. This system will shutdown in 1 hour.1511 /// {Windows Evaluation Notification} The evaluation period for this installation of Windows has expired. This system will shutdown in 1 hour.
2208 /// To restore access to this installation of Windows, upgrade this installation by using a licensed distribution of this product.1512 /// To restore access to this installation of Windows, upgrade this installation by using a licensed distribution of this product.
2209 EVALUATION_EXPIRATION = 0xC0000268,1513 EVALUATION_EXPIRATION = 0xC0000268,
2210
2211 /// {Illegal System DLL Relocation} The system DLL %hs was relocated in memory. The application will not run properly.1514 /// {Illegal System DLL Relocation} The system DLL %hs was relocated in memory. The application will not run properly.
2212 /// The relocation occurred because the DLL %hs occupied an address range that is reserved for Windows system DLLs.1515 /// The relocation occurred because the DLL %hs occupied an address range that is reserved for Windows system DLLs.
2213 /// The vendor supplying the DLL should be contacted for a new DLL.1516 /// The vendor supplying the DLL should be contacted for a new DLL.
2214 ILLEGAL_DLL_RELOCATION = 0xC0000269,1517 ILLEGAL_DLL_RELOCATION = 0xC0000269,
2215
2216 /// {License Violation} The system has detected tampering with your registered product type.1518 /// {License Violation} The system has detected tampering with your registered product type.
2217 /// This is a violation of your software license. Tampering with the product type is not permitted.1519 /// This is a violation of your software license. Tampering with the product type is not permitted.
2218 LICENSE_VIOLATION = 0xC000026A,1520 LICENSE_VIOLATION = 0xC000026A,
2219
2220 /// {DLL Initialization Failed} The application failed to initialize because the window station is shutting down.1521 /// {DLL Initialization Failed} The application failed to initialize because the window station is shutting down.
2221 DLL_INIT_FAILED_LOGOFF = 0xC000026B,1522 DLL_INIT_FAILED_LOGOFF = 0xC000026B,
2222
2223 /// {Unable to Load Device Driver} %hs device driver could not be loaded. Error Status was 0x%x.1523 /// {Unable to Load Device Driver} %hs device driver could not be loaded. Error Status was 0x%x.
2224 DRIVER_UNABLE_TO_LOAD = 0xC000026C,1524 DRIVER_UNABLE_TO_LOAD = 0xC000026C,
2225
2226 /// DFS is unavailable on the contacted server.1525 /// DFS is unavailable on the contacted server.
2227 DFS_UNAVAILABLE = 0xC000026D,1526 DFS_UNAVAILABLE = 0xC000026D,
2228
2229 /// An operation was attempted to a volume after it was dismounted.1527 /// An operation was attempted to a volume after it was dismounted.
2230 VOLUME_DISMOUNTED = 0xC000026E,1528 VOLUME_DISMOUNTED = 0xC000026E,
2231
2232 /// An internal error occurred in the Win32 x86 emulation subsystem.1529 /// An internal error occurred in the Win32 x86 emulation subsystem.
2233 WX86_INTERNAL_ERROR = 0xC000026F,1530 WX86_INTERNAL_ERROR = 0xC000026F,
2234
2235 /// Win32 x86 emulation subsystem floating-point stack check.1531 /// Win32 x86 emulation subsystem floating-point stack check.
2236 WX86_FLOAT_STACK_CHECK = 0xC0000270,1532 WX86_FLOAT_STACK_CHECK = 0xC0000270,
2237
2238 /// The validation process needs to continue on to the next step.1533 /// The validation process needs to continue on to the next step.
2239 VALIDATE_CONTINUE = 0xC0000271,1534 VALIDATE_CONTINUE = 0xC0000271,
2240
2241 /// There was no match for the specified key in the index.1535 /// There was no match for the specified key in the index.
2242 NO_MATCH = 0xC0000272,1536 NO_MATCH = 0xC0000272,
2243
2244 /// There are no more matches for the current index enumeration.1537 /// There are no more matches for the current index enumeration.
2245 NO_MORE_MATCHES = 0xC0000273,1538 NO_MORE_MATCHES = 0xC0000273,
2246
2247 /// The NTFS file or directory is not a reparse point.1539 /// The NTFS file or directory is not a reparse point.
2248 NOT_A_REPARSE_POINT = 0xC0000275,1540 NOT_A_REPARSE_POINT = 0xC0000275,
2249
2250 /// The Windows I/O reparse tag passed for the NTFS reparse point is invalid.1541 /// The Windows I/O reparse tag passed for the NTFS reparse point is invalid.
2251 IO_REPARSE_TAG_INVALID = 0xC0000276,1542 IO_REPARSE_TAG_INVALID = 0xC0000276,
2252
2253 /// The Windows I/O reparse tag does not match the one that is in the NTFS reparse point.1543 /// The Windows I/O reparse tag does not match the one that is in the NTFS reparse point.
2254 IO_REPARSE_TAG_MISMATCH = 0xC0000277,1544 IO_REPARSE_TAG_MISMATCH = 0xC0000277,
2255
2256 /// The user data passed for the NTFS reparse point is invalid.1545 /// The user data passed for the NTFS reparse point is invalid.
2257 IO_REPARSE_DATA_INVALID = 0xC0000278,1546 IO_REPARSE_DATA_INVALID = 0xC0000278,
2258
2259 /// The layered file system driver for this I/O tag did not handle it when needed.1547 /// The layered file system driver for this I/O tag did not handle it when needed.
2260 IO_REPARSE_TAG_NOT_HANDLED = 0xC0000279,1548 IO_REPARSE_TAG_NOT_HANDLED = 0xC0000279,
2261
2262 /// The NTFS symbolic link could not be resolved even though the initial file name is valid.1549 /// The NTFS symbolic link could not be resolved even though the initial file name is valid.
2263 REPARSE_POINT_NOT_RESOLVED = 0xC0000280,1550 REPARSE_POINT_NOT_RESOLVED = 0xC0000280,
2264
2265 /// The NTFS directory is a reparse point.1551 /// The NTFS directory is a reparse point.
2266 DIRECTORY_IS_A_REPARSE_POINT = 0xC0000281,1552 DIRECTORY_IS_A_REPARSE_POINT = 0xC0000281,
2267
2268 /// The range could not be added to the range list because of a conflict.1553 /// The range could not be added to the range list because of a conflict.
2269 RANGE_LIST_CONFLICT = 0xC0000282,1554 RANGE_LIST_CONFLICT = 0xC0000282,
2270
2271 /// The specified medium changer source element contains no media.1555 /// The specified medium changer source element contains no media.
2272 SOURCE_ELEMENT_EMPTY = 0xC0000283,1556 SOURCE_ELEMENT_EMPTY = 0xC0000283,
2273
2274 /// The specified medium changer destination element already contains media.1557 /// The specified medium changer destination element already contains media.
2275 DESTINATION_ELEMENT_FULL = 0xC0000284,1558 DESTINATION_ELEMENT_FULL = 0xC0000284,
2276
2277 /// The specified medium changer element does not exist.1559 /// The specified medium changer element does not exist.
2278 ILLEGAL_ELEMENT_ADDRESS = 0xC0000285,1560 ILLEGAL_ELEMENT_ADDRESS = 0xC0000285,
2279
2280 /// The specified element is contained in a magazine that is no longer present.1561 /// The specified element is contained in a magazine that is no longer present.
2281 MAGAZINE_NOT_PRESENT = 0xC0000286,1562 MAGAZINE_NOT_PRESENT = 0xC0000286,
2282
2283 /// The device requires re-initialization due to hardware errors.1563 /// The device requires re-initialization due to hardware errors.
2284 REINITIALIZATION_NEEDED = 0xC0000287,1564 REINITIALIZATION_NEEDED = 0xC0000287,
2285
2286 /// The file encryption attempt failed.1565 /// The file encryption attempt failed.
2287 ENCRYPTION_FAILED = 0xC000028A,1566 ENCRYPTION_FAILED = 0xC000028A,
2288
2289 /// The file decryption attempt failed.1567 /// The file decryption attempt failed.
2290 DECRYPTION_FAILED = 0xC000028B,1568 DECRYPTION_FAILED = 0xC000028B,
2291
2292 /// The specified range could not be found in the range list.1569 /// The specified range could not be found in the range list.
2293 RANGE_NOT_FOUND = 0xC000028C,1570 RANGE_NOT_FOUND = 0xC000028C,
2294
2295 /// There is no encryption recovery policy configured for this system.1571 /// There is no encryption recovery policy configured for this system.
2296 NO_RECOVERY_POLICY = 0xC000028D,1572 NO_RECOVERY_POLICY = 0xC000028D,
2297
2298 /// The required encryption driver is not loaded for this system.1573 /// The required encryption driver is not loaded for this system.
2299 NO_EFS = 0xC000028E,1574 NO_EFS = 0xC000028E,
2300
2301 /// The file was encrypted with a different encryption driver than is currently loaded.1575 /// The file was encrypted with a different encryption driver than is currently loaded.
2302 WRONG_EFS = 0xC000028F,1576 WRONG_EFS = 0xC000028F,
2303
2304 /// There are no EFS keys defined for the user.1577 /// There are no EFS keys defined for the user.
2305 NO_USER_KEYS = 0xC0000290,1578 NO_USER_KEYS = 0xC0000290,
2306
2307 /// The specified file is not encrypted.1579 /// The specified file is not encrypted.
2308 FILE_NOT_ENCRYPTED = 0xC0000291,1580 FILE_NOT_ENCRYPTED = 0xC0000291,
2309
2310 /// The specified file is not in the defined EFS export format.1581 /// The specified file is not in the defined EFS export format.
2311 NOT_EXPORT_FORMAT = 0xC0000292,1582 NOT_EXPORT_FORMAT = 0xC0000292,
2312
2313 /// The specified file is encrypted and the user does not have the ability to decrypt it.1583 /// The specified file is encrypted and the user does not have the ability to decrypt it.
2314 FILE_ENCRYPTED = 0xC0000293,1584 FILE_ENCRYPTED = 0xC0000293,
2315
2316 /// The GUID passed was not recognized as valid by a WMI data provider.1585 /// The GUID passed was not recognized as valid by a WMI data provider.
2317 WMI_GUID_NOT_FOUND = 0xC0000295,1586 WMI_GUID_NOT_FOUND = 0xC0000295,
2318
2319 /// The instance name passed was not recognized as valid by a WMI data provider.1587 /// The instance name passed was not recognized as valid by a WMI data provider.
2320 WMI_INSTANCE_NOT_FOUND = 0xC0000296,1588 WMI_INSTANCE_NOT_FOUND = 0xC0000296,
2321
2322 /// The data item ID passed was not recognized as valid by a WMI data provider.1589 /// The data item ID passed was not recognized as valid by a WMI data provider.
2323 WMI_ITEMID_NOT_FOUND = 0xC0000297,1590 WMI_ITEMID_NOT_FOUND = 0xC0000297,
2324
2325 /// The WMI request could not be completed and should be retried.1591 /// The WMI request could not be completed and should be retried.
2326 WMI_TRY_AGAIN = 0xC0000298,1592 WMI_TRY_AGAIN = 0xC0000298,
2327
2328 /// The policy object is shared and can only be modified at the root.1593 /// The policy object is shared and can only be modified at the root.
2329 SHARED_POLICY = 0xC0000299,1594 SHARED_POLICY = 0xC0000299,
2330
2331 /// The policy object does not exist when it should.1595 /// The policy object does not exist when it should.
2332 POLICY_OBJECT_NOT_FOUND = 0xC000029A,1596 POLICY_OBJECT_NOT_FOUND = 0xC000029A,
2333
2334 /// The requested policy information only lives in the Ds.1597 /// The requested policy information only lives in the Ds.
2335 POLICY_ONLY_IN_DS = 0xC000029B,1598 POLICY_ONLY_IN_DS = 0xC000029B,
2336
2337 /// The volume must be upgraded to enable this feature.1599 /// The volume must be upgraded to enable this feature.
2338 VOLUME_NOT_UPGRADED = 0xC000029C,1600 VOLUME_NOT_UPGRADED = 0xC000029C,
2339
2340 /// The remote storage service is not operational at this time.1601 /// The remote storage service is not operational at this time.
2341 REMOTE_STORAGE_NOT_ACTIVE = 0xC000029D,1602 REMOTE_STORAGE_NOT_ACTIVE = 0xC000029D,
2342
2343 /// The remote storage service encountered a media error.1603 /// The remote storage service encountered a media error.
2344 REMOTE_STORAGE_MEDIA_ERROR = 0xC000029E,1604 REMOTE_STORAGE_MEDIA_ERROR = 0xC000029E,
2345
2346 /// The tracking (workstation) service is not running.1605 /// The tracking (workstation) service is not running.
2347 NO_TRACKING_SERVICE = 0xC000029F,1606 NO_TRACKING_SERVICE = 0xC000029F,
2348
2349 /// The server process is running under a SID that is different from the SID that is required by client.1607 /// The server process is running under a SID that is different from the SID that is required by client.
2350 SERVER_SID_MISMATCH = 0xC00002A0,1608 SERVER_SID_MISMATCH = 0xC00002A0,
2351
2352 /// The specified directory service attribute or value does not exist.1609 /// The specified directory service attribute or value does not exist.
2353 DS_NO_ATTRIBUTE_OR_VALUE = 0xC00002A1,1610 DS_NO_ATTRIBUTE_OR_VALUE = 0xC00002A1,
2354
2355 /// The attribute syntax specified to the directory service is invalid.1611 /// The attribute syntax specified to the directory service is invalid.
2356 DS_INVALID_ATTRIBUTE_SYNTAX = 0xC00002A2,1612 DS_INVALID_ATTRIBUTE_SYNTAX = 0xC00002A2,
2357
2358 /// The attribute type specified to the directory service is not defined.1613 /// The attribute type specified to the directory service is not defined.
2359 DS_ATTRIBUTE_TYPE_UNDEFINED = 0xC00002A3,1614 DS_ATTRIBUTE_TYPE_UNDEFINED = 0xC00002A3,
2360
2361 /// The specified directory service attribute or value already exists.1615 /// The specified directory service attribute or value already exists.
2362 DS_ATTRIBUTE_OR_VALUE_EXISTS = 0xC00002A4,1616 DS_ATTRIBUTE_OR_VALUE_EXISTS = 0xC00002A4,
2363
2364 /// The directory service is busy.1617 /// The directory service is busy.
2365 DS_BUSY = 0xC00002A5,1618 DS_BUSY = 0xC00002A5,
2366
2367 /// The directory service is unavailable.1619 /// The directory service is unavailable.
2368 DS_UNAVAILABLE = 0xC00002A6,1620 DS_UNAVAILABLE = 0xC00002A6,
2369
2370 /// The directory service was unable to allocate a relative identifier.1621 /// The directory service was unable to allocate a relative identifier.
2371 DS_NO_RIDS_ALLOCATED = 0xC00002A7,1622 DS_NO_RIDS_ALLOCATED = 0xC00002A7,
2372
2373 /// The directory service has exhausted the pool of relative identifiers.1623 /// The directory service has exhausted the pool of relative identifiers.
2374 DS_NO_MORE_RIDS = 0xC00002A8,1624 DS_NO_MORE_RIDS = 0xC00002A8,
2375
2376 /// The requested operation could not be performed because the directory service is not the master for that type of operation.1625 /// The requested operation could not be performed because the directory service is not the master for that type of operation.
2377 DS_INCORRECT_ROLE_OWNER = 0xC00002A9,1626 DS_INCORRECT_ROLE_OWNER = 0xC00002A9,
2378
2379 /// The directory service was unable to initialize the subsystem that allocates relative identifiers.1627 /// The directory service was unable to initialize the subsystem that allocates relative identifiers.
2380 DS_RIDMGR_INIT_ERROR = 0xC00002AA,1628 DS_RIDMGR_INIT_ERROR = 0xC00002AA,
2381
2382 /// The requested operation did not satisfy one or more constraints that are associated with the class of the object.1629 /// The requested operation did not satisfy one or more constraints that are associated with the class of the object.
2383 DS_OBJ_CLASS_VIOLATION = 0xC00002AB,1630 DS_OBJ_CLASS_VIOLATION = 0xC00002AB,
2384
2385 /// The directory service can perform the requested operation only on a leaf object.1631 /// The directory service can perform the requested operation only on a leaf object.
2386 DS_CANT_ON_NON_LEAF = 0xC00002AC,1632 DS_CANT_ON_NON_LEAF = 0xC00002AC,
2387
2388 /// The directory service cannot perform the requested operation on the Relatively Defined Name (RDN) attribute of an object.1633 /// The directory service cannot perform the requested operation on the Relatively Defined Name (RDN) attribute of an object.
2389 DS_CANT_ON_RDN = 0xC00002AD,1634 DS_CANT_ON_RDN = 0xC00002AD,
2390
2391 /// The directory service detected an attempt to modify the object class of an object.1635 /// The directory service detected an attempt to modify the object class of an object.
2392 DS_CANT_MOD_OBJ_CLASS = 0xC00002AE,1636 DS_CANT_MOD_OBJ_CLASS = 0xC00002AE,
2393
2394 /// An error occurred while performing a cross domain move operation.1637 /// An error occurred while performing a cross domain move operation.
2395 DS_CROSS_DOM_MOVE_FAILED = 0xC00002AF,1638 DS_CROSS_DOM_MOVE_FAILED = 0xC00002AF,
2396
2397 /// Unable to contact the global catalog server.1639 /// Unable to contact the global catalog server.
2398 DS_GC_NOT_AVAILABLE = 0xC00002B0,1640 DS_GC_NOT_AVAILABLE = 0xC00002B0,
2399
2400 /// The requested operation requires a directory service, and none was available.1641 /// The requested operation requires a directory service, and none was available.
2401 DIRECTORY_SERVICE_REQUIRED = 0xC00002B1,1642 DIRECTORY_SERVICE_REQUIRED = 0xC00002B1,
2402
2403 /// The reparse attribute cannot be set because it is incompatible with an existing attribute.1643 /// The reparse attribute cannot be set because it is incompatible with an existing attribute.
2404 REPARSE_ATTRIBUTE_CONFLICT = 0xC00002B2,1644 REPARSE_ATTRIBUTE_CONFLICT = 0xC00002B2,
2405
2406 /// A group marked "use for deny only" cannot be enabled.1645 /// A group marked "use for deny only" cannot be enabled.
2407 CANT_ENABLE_DENY_ONLY = 0xC00002B3,1646 CANT_ENABLE_DENY_ONLY = 0xC00002B3,
2408
2409 /// {EXCEPTION} Multiple floating-point faults.1647 /// {EXCEPTION} Multiple floating-point faults.
2410 FLOAT_MULTIPLE_FAULTS = 0xC00002B4,1648 FLOAT_MULTIPLE_FAULTS = 0xC00002B4,
2411
2412 /// {EXCEPTION} Multiple floating-point traps.1649 /// {EXCEPTION} Multiple floating-point traps.
2413 FLOAT_MULTIPLE_TRAPS = 0xC00002B5,1650 FLOAT_MULTIPLE_TRAPS = 0xC00002B5,
2414
2415 /// The device has been removed.1651 /// The device has been removed.
2416 DEVICE_REMOVED = 0xC00002B6,1652 DEVICE_REMOVED = 0xC00002B6,
2417
2418 /// The volume change journal is being deleted.1653 /// The volume change journal is being deleted.
2419 JOURNAL_DELETE_IN_PROGRESS = 0xC00002B7,1654 JOURNAL_DELETE_IN_PROGRESS = 0xC00002B7,
2420
2421 /// The volume change journal is not active.1655 /// The volume change journal is not active.
2422 JOURNAL_NOT_ACTIVE = 0xC00002B8,1656 JOURNAL_NOT_ACTIVE = 0xC00002B8,
2423
2424 /// The requested interface is not supported.1657 /// The requested interface is not supported.
2425 NOINTERFACE = 0xC00002B9,1658 NOINTERFACE = 0xC00002B9,
2426
2427 /// A directory service resource limit has been exceeded.1659 /// A directory service resource limit has been exceeded.
2428 DS_ADMIN_LIMIT_EXCEEDED = 0xC00002C1,1660 DS_ADMIN_LIMIT_EXCEEDED = 0xC00002C1,
2429
2430 /// {System Standby Failed} The driver %hs does not support standby mode.1661 /// {System Standby Failed} The driver %hs does not support standby mode.
2431 /// Updating this driver allows the system to go to standby mode.1662 /// Updating this driver allows the system to go to standby mode.
2432 DRIVER_FAILED_SLEEP = 0xC00002C2,1663 DRIVER_FAILED_SLEEP = 0xC00002C2,
2433
2434 /// Mutual Authentication failed. The server password is out of date at the domain controller.1664 /// Mutual Authentication failed. The server password is out of date at the domain controller.
2435 MUTUAL_AUTHENTICATION_FAILED = 0xC00002C3,1665 MUTUAL_AUTHENTICATION_FAILED = 0xC00002C3,
2436
2437 /// The system file %1 has become corrupt and has been replaced.1666 /// The system file %1 has become corrupt and has been replaced.
2438 CORRUPT_SYSTEM_FILE = 0xC00002C4,1667 CORRUPT_SYSTEM_FILE = 0xC00002C4,
2439
2440 /// {EXCEPTION} Alignment Error A data type misalignment error was detected in a load or store instruction.1668 /// {EXCEPTION} Alignment Error A data type misalignment error was detected in a load or store instruction.
2441 DATATYPE_MISALIGNMENT_ERROR = 0xC00002C5,1669 DATATYPE_MISALIGNMENT_ERROR = 0xC00002C5,
2442
2443 /// The WMI data item or data block is read-only.1670 /// The WMI data item or data block is read-only.
2444 WMI_READ_ONLY = 0xC00002C6,1671 WMI_READ_ONLY = 0xC00002C6,
2445
2446 /// The WMI data item or data block could not be changed.1672 /// The WMI data item or data block could not be changed.
2447 WMI_SET_FAILURE = 0xC00002C7,1673 WMI_SET_FAILURE = 0xC00002C7,
2448
2449 /// {Virtual Memory Minimum Too Low} Your system is low on virtual memory.1674 /// {Virtual Memory Minimum Too Low} Your system is low on virtual memory.
2450 /// Windows is increasing the size of your virtual memory paging file.1675 /// Windows is increasing the size of your virtual memory paging file.
2451 /// During this process, memory requests for some applications might be denied. For more information, see Help.1676 /// During this process, memory requests for some applications might be denied. For more information, see Help.
2452 COMMITMENT_MINIMUM = 0xC00002C8,1677 COMMITMENT_MINIMUM = 0xC00002C8,
2453
2454 /// {EXCEPTION} Register NaT consumption faults.1678 /// {EXCEPTION} Register NaT consumption faults.
2455 /// A NaT value is consumed on a non-speculative instruction.1679 /// A NaT value is consumed on a non-speculative instruction.
2456 REG_NAT_CONSUMPTION = 0xC00002C9,1680 REG_NAT_CONSUMPTION = 0xC00002C9,
2457
2458 /// The transport element of the medium changer contains media, which is causing the operation to fail.1681 /// The transport element of the medium changer contains media, which is causing the operation to fail.
2459 TRANSPORT_FULL = 0xC00002CA,1682 TRANSPORT_FULL = 0xC00002CA,
2460
2461 /// Security Accounts Manager initialization failed because of the following error: %hs Error Status: 0x%x.1683 /// Security Accounts Manager initialization failed because of the following error: %hs Error Status: 0x%x.
2462 /// Click OK to shut down this system and restart in Directory Services Restore Mode.1684 /// Click OK to shut down this system and restart in Directory Services Restore Mode.
2463 /// Check the event log for more detailed information.1685 /// Check the event log for more detailed information.
2464 DS_SAM_INIT_FAILURE = 0xC00002CB,1686 DS_SAM_INIT_FAILURE = 0xC00002CB,
2465
2466 /// This operation is supported only when you are connected to the server.1687 /// This operation is supported only when you are connected to the server.
2467 ONLY_IF_CONNECTED = 0xC00002CC,1688 ONLY_IF_CONNECTED = 0xC00002CC,
2468
2469 /// Only an administrator can modify the membership list of an administrative group.1689 /// Only an administrator can modify the membership list of an administrative group.
2470 DS_SENSITIVE_GROUP_VIOLATION = 0xC00002CD,1690 DS_SENSITIVE_GROUP_VIOLATION = 0xC00002CD,
2471
2472 /// A device was removed so enumeration must be restarted.1691 /// A device was removed so enumeration must be restarted.
2473 PNP_RESTART_ENUMERATION = 0xC00002CE,1692 PNP_RESTART_ENUMERATION = 0xC00002CE,
2474
2475 /// The journal entry has been deleted from the journal.1693 /// The journal entry has been deleted from the journal.
2476 JOURNAL_ENTRY_DELETED = 0xC00002CF,1694 JOURNAL_ENTRY_DELETED = 0xC00002CF,
2477
2478 /// Cannot change the primary group ID of a domain controller account.1695 /// Cannot change the primary group ID of a domain controller account.
2479 DS_CANT_MOD_PRIMARYGROUPID = 0xC00002D0,1696 DS_CANT_MOD_PRIMARYGROUPID = 0xC00002D0,
2480
2481 /// {Fatal System Error} The system image %s is not properly signed.1697 /// {Fatal System Error} The system image %s is not properly signed.
2482 /// The file has been replaced with the signed file. The system has been shut down.1698 /// The file has been replaced with the signed file. The system has been shut down.
2483 SYSTEM_IMAGE_BAD_SIGNATURE = 0xC00002D1,1699 SYSTEM_IMAGE_BAD_SIGNATURE = 0xC00002D1,
2484
2485 /// The device will not start without a reboot.1700 /// The device will not start without a reboot.
2486 PNP_REBOOT_REQUIRED = 0xC00002D2,1701 PNP_REBOOT_REQUIRED = 0xC00002D2,
2487
2488 /// The power state of the current device cannot support this request.1702 /// The power state of the current device cannot support this request.
2489 POWER_STATE_INVALID = 0xC00002D3,1703 POWER_STATE_INVALID = 0xC00002D3,
2490
2491 /// The specified group type is invalid.1704 /// The specified group type is invalid.
2492 DS_INVALID_GROUP_TYPE = 0xC00002D4,1705 DS_INVALID_GROUP_TYPE = 0xC00002D4,
2493
2494 /// In a mixed domain, no nesting of a global group if the group is security enabled.1706 /// In a mixed domain, no nesting of a global group if the group is security enabled.
2495 DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN = 0xC00002D5,1707 DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN = 0xC00002D5,
2496
2497 /// In a mixed domain, cannot nest local groups with other local groups, if the group is security enabled.1708 /// In a mixed domain, cannot nest local groups with other local groups, if the group is security enabled.
2498 DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN = 0xC00002D6,1709 DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN = 0xC00002D6,
2499
2500 /// A global group cannot have a local group as a member.1710 /// A global group cannot have a local group as a member.
2501 DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER = 0xC00002D7,1711 DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER = 0xC00002D7,
2502
2503 /// A global group cannot have a universal group as a member.1712 /// A global group cannot have a universal group as a member.
2504 DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER = 0xC00002D8,1713 DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER = 0xC00002D8,
2505
2506 /// A universal group cannot have a local group as a member.1714 /// A universal group cannot have a local group as a member.
2507 DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER = 0xC00002D9,1715 DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER = 0xC00002D9,
2508
2509 /// A global group cannot have a cross-domain member.1716 /// A global group cannot have a cross-domain member.
2510 DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER = 0xC00002DA,1717 DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER = 0xC00002DA,
2511
2512 /// A local group cannot have another cross-domain local group as a member.1718 /// A local group cannot have another cross-domain local group as a member.
2513 DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER = 0xC00002DB,1719 DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER = 0xC00002DB,
2514
2515 /// Cannot change to a security-disabled group because primary members are in this group.1720 /// Cannot change to a security-disabled group because primary members are in this group.
2516 DS_HAVE_PRIMARY_MEMBERS = 0xC00002DC,1721 DS_HAVE_PRIMARY_MEMBERS = 0xC00002DC,
2517
2518 /// The WMI operation is not supported by the data block or method.1722 /// The WMI operation is not supported by the data block or method.
2519 WMI_NOT_SUPPORTED = 0xC00002DD,1723 WMI_NOT_SUPPORTED = 0xC00002DD,
2520
2521 /// There is not enough power to complete the requested operation.1724 /// There is not enough power to complete the requested operation.
2522 INSUFFICIENT_POWER = 0xC00002DE,1725 INSUFFICIENT_POWER = 0xC00002DE,
2523
2524 /// The Security Accounts Manager needs to get the boot password.1726 /// The Security Accounts Manager needs to get the boot password.
2525 SAM_NEED_BOOTKEY_PASSWORD = 0xC00002DF,1727 SAM_NEED_BOOTKEY_PASSWORD = 0xC00002DF,
2526
2527 /// The Security Accounts Manager needs to get the boot key from the floppy disk.1728 /// The Security Accounts Manager needs to get the boot key from the floppy disk.
2528 SAM_NEED_BOOTKEY_FLOPPY = 0xC00002E0,1729 SAM_NEED_BOOTKEY_FLOPPY = 0xC00002E0,
2529
2530 /// The directory service cannot start.1730 /// The directory service cannot start.
2531 DS_CANT_START = 0xC00002E1,1731 DS_CANT_START = 0xC00002E1,
2532
2533 /// The directory service could not start because of the following error: %hs Error Status: 0x%x.1732 /// The directory service could not start because of the following error: %hs Error Status: 0x%x.
2534 /// Click OK to shut down this system and restart in Directory Services Restore Mode.1733 /// Click OK to shut down this system and restart in Directory Services Restore Mode.
2535 /// Check the event log for more detailed information.1734 /// Check the event log for more detailed information.
2536 DS_INIT_FAILURE = 0xC00002E2,1735 DS_INIT_FAILURE = 0xC00002E2,
2537
2538 /// The Security Accounts Manager initialization failed because of the following error: %hs Error Status: 0x%x.1736 /// The Security Accounts Manager initialization failed because of the following error: %hs Error Status: 0x%x.
2539 /// Click OK to shut down this system and restart in Safe Mode.1737 /// Click OK to shut down this system and restart in Safe Mode.
2540 /// Check the event log for more detailed information.1738 /// Check the event log for more detailed information.
2541 SAM_INIT_FAILURE = 0xC00002E3,1739 SAM_INIT_FAILURE = 0xC00002E3,
2542
2543 /// The requested operation can be performed only on a global catalog server.1740 /// The requested operation can be performed only on a global catalog server.
2544 DS_GC_REQUIRED = 0xC00002E4,1741 DS_GC_REQUIRED = 0xC00002E4,
2545
2546 /// A local group can only be a member of other local groups in the same domain.1742 /// A local group can only be a member of other local groups in the same domain.
2547 DS_LOCAL_MEMBER_OF_LOCAL_ONLY = 0xC00002E5,1743 DS_LOCAL_MEMBER_OF_LOCAL_ONLY = 0xC00002E5,
2548
2549 /// Foreign security principals cannot be members of universal groups.1744 /// Foreign security principals cannot be members of universal groups.
2550 DS_NO_FPO_IN_UNIVERSAL_GROUPS = 0xC00002E6,1745 DS_NO_FPO_IN_UNIVERSAL_GROUPS = 0xC00002E6,
2551
2552 /// Your computer could not be joined to the domain.1746 /// Your computer could not be joined to the domain.
2553 /// You have exceeded the maximum number of computer accounts you are allowed to create in this domain.1747 /// You have exceeded the maximum number of computer accounts you are allowed to create in this domain.
2554 /// Contact your system administrator to have this limit reset or increased.1748 /// Contact your system administrator to have this limit reset or increased.
2555 DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED = 0xC00002E7,1749 DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED = 0xC00002E7,
2556
2557 /// This operation cannot be performed on the current domain.1750 /// This operation cannot be performed on the current domain.
2558 CURRENT_DOMAIN_NOT_ALLOWED = 0xC00002E9,1751 CURRENT_DOMAIN_NOT_ALLOWED = 0xC00002E9,
2559
2560 /// The directory or file cannot be created.1752 /// The directory or file cannot be created.
2561 CANNOT_MAKE = 0xC00002EA,1753 CANNOT_MAKE = 0xC00002EA,
2562
2563 /// The system is in the process of shutting down.1754 /// The system is in the process of shutting down.
2564 SYSTEM_SHUTDOWN = 0xC00002EB,1755 SYSTEM_SHUTDOWN = 0xC00002EB,
2565
2566 /// Directory Services could not start because of the following error: %hs Error Status: 0x%x. Click OK to shut down the system.1756 /// Directory Services could not start because of the following error: %hs Error Status: 0x%x. Click OK to shut down the system.
2567 /// You can use the recovery console to diagnose the system further.1757 /// You can use the recovery console to diagnose the system further.
2568 DS_INIT_FAILURE_CONSOLE = 0xC00002EC,1758 DS_INIT_FAILURE_CONSOLE = 0xC00002EC,
2569
2570 /// Security Accounts Manager initialization failed because of the following error: %hs Error Status: 0x%x. Click OK to shut down the system.1759 /// Security Accounts Manager initialization failed because of the following error: %hs Error Status: 0x%x. Click OK to shut down the system.
2571 /// You can use the recovery console to diagnose the system further.1760 /// You can use the recovery console to diagnose the system further.
2572 DS_SAM_INIT_FAILURE_CONSOLE = 0xC00002ED,1761 DS_SAM_INIT_FAILURE_CONSOLE = 0xC00002ED,
2573
2574 /// A security context was deleted before the context was completed. This is considered a logon failure.1762 /// A security context was deleted before the context was completed. This is considered a logon failure.
2575 UNFINISHED_CONTEXT_DELETED = 0xC00002EE,1763 UNFINISHED_CONTEXT_DELETED = 0xC00002EE,
2576
2577 /// The client is trying to negotiate a context and the server requires user-to-user but did not send a TGT reply.1764 /// The client is trying to negotiate a context and the server requires user-to-user but did not send a TGT reply.
2578 NO_TGT_REPLY = 0xC00002EF,1765 NO_TGT_REPLY = 0xC00002EF,
2579
2580 /// An object ID was not found in the file.1766 /// An object ID was not found in the file.
2581 OBJECTID_NOT_FOUND = 0xC00002F0,1767 OBJECTID_NOT_FOUND = 0xC00002F0,
2582
2583 /// Unable to accomplish the requested task because the local machine does not have any IP addresses.1768 /// Unable to accomplish the requested task because the local machine does not have any IP addresses.
2584 NO_IP_ADDRESSES = 0xC00002F1,1769 NO_IP_ADDRESSES = 0xC00002F1,
2585
2586 /// The supplied credential handle does not match the credential that is associated with the security context.1770 /// The supplied credential handle does not match the credential that is associated with the security context.
2587 WRONG_CREDENTIAL_HANDLE = 0xC00002F2,1771 WRONG_CREDENTIAL_HANDLE = 0xC00002F2,
2588
2589 /// The crypto system or checksum function is invalid because a required function is unavailable.1772 /// The crypto system or checksum function is invalid because a required function is unavailable.
2590 CRYPTO_SYSTEM_INVALID = 0xC00002F3,1773 CRYPTO_SYSTEM_INVALID = 0xC00002F3,
2591
2592 /// The number of maximum ticket referrals has been exceeded.1774 /// The number of maximum ticket referrals has been exceeded.
2593 MAX_REFERRALS_EXCEEDED = 0xC00002F4,1775 MAX_REFERRALS_EXCEEDED = 0xC00002F4,
2594
2595 /// The local machine must be a Kerberos KDC (domain controller) and it is not.1776 /// The local machine must be a Kerberos KDC (domain controller) and it is not.
2596 MUST_BE_KDC = 0xC00002F5,1777 MUST_BE_KDC = 0xC00002F5,
2597
2598 /// The other end of the security negotiation requires strong crypto but it is not supported on the local machine.1778 /// The other end of the security negotiation requires strong crypto but it is not supported on the local machine.
2599 STRONG_CRYPTO_NOT_SUPPORTED = 0xC00002F6,1779 STRONG_CRYPTO_NOT_SUPPORTED = 0xC00002F6,
2600
2601 /// The KDC reply contained more than one principal name.1780 /// The KDC reply contained more than one principal name.
2602 TOO_MANY_PRINCIPALS = 0xC00002F7,1781 TOO_MANY_PRINCIPALS = 0xC00002F7,
2603
2604 /// Expected to find PA data for a hint of what etype to use, but it was not found.1782 /// Expected to find PA data for a hint of what etype to use, but it was not found.
2605 NO_PA_DATA = 0xC00002F8,1783 NO_PA_DATA = 0xC00002F8,
2606
2607 /// The client certificate does not contain a valid UPN, or does not match the client name in the logon request. Contact your administrator.1784 /// The client certificate does not contain a valid UPN, or does not match the client name in the logon request. Contact your administrator.
2608 PKINIT_NAME_MISMATCH = 0xC00002F9,1785 PKINIT_NAME_MISMATCH = 0xC00002F9,
2609
2610 /// Smart card logon is required and was not used.1786 /// Smart card logon is required and was not used.
2611 SMARTCARD_LOGON_REQUIRED = 0xC00002FA,1787 SMARTCARD_LOGON_REQUIRED = 0xC00002FA,
2612
2613 /// An invalid request was sent to the KDC.1788 /// An invalid request was sent to the KDC.
2614 KDC_INVALID_REQUEST = 0xC00002FB,1789 KDC_INVALID_REQUEST = 0xC00002FB,
2615
2616 /// The KDC was unable to generate a referral for the service requested.1790 /// The KDC was unable to generate a referral for the service requested.
2617 KDC_UNABLE_TO_REFER = 0xC00002FC,1791 KDC_UNABLE_TO_REFER = 0xC00002FC,
2618
2619 /// The encryption type requested is not supported by the KDC.1792 /// The encryption type requested is not supported by the KDC.
2620 KDC_UNKNOWN_ETYPE = 0xC00002FD,1793 KDC_UNKNOWN_ETYPE = 0xC00002FD,
2621
2622 /// A system shutdown is in progress.1794 /// A system shutdown is in progress.
2623 SHUTDOWN_IN_PROGRESS = 0xC00002FE,1795 SHUTDOWN_IN_PROGRESS = 0xC00002FE,
2624
2625 /// The server machine is shutting down.1796 /// The server machine is shutting down.
2626 SERVER_SHUTDOWN_IN_PROGRESS = 0xC00002FF,1797 SERVER_SHUTDOWN_IN_PROGRESS = 0xC00002FF,
2627
2628 /// This operation is not supported on a computer running Windows Server 2003 operating system for Small Business Server.1798 /// This operation is not supported on a computer running Windows Server 2003 operating system for Small Business Server.
2629 NOT_SUPPORTED_ON_SBS = 0xC0000300,1799 NOT_SUPPORTED_ON_SBS = 0xC0000300,
2630
2631 /// The WMI GUID is no longer available.1800 /// The WMI GUID is no longer available.
2632 WMI_GUID_DISCONNECTED = 0xC0000301,1801 WMI_GUID_DISCONNECTED = 0xC0000301,
2633
2634 /// Collection or events for the WMI GUID is already disabled.1802 /// Collection or events for the WMI GUID is already disabled.
2635 WMI_ALREADY_DISABLED = 0xC0000302,1803 WMI_ALREADY_DISABLED = 0xC0000302,
2636
2637 /// Collection or events for the WMI GUID is already enabled.1804 /// Collection or events for the WMI GUID is already enabled.
2638 WMI_ALREADY_ENABLED = 0xC0000303,1805 WMI_ALREADY_ENABLED = 0xC0000303,
2639
2640 /// The master file table on the volume is too fragmented to complete this operation.1806 /// The master file table on the volume is too fragmented to complete this operation.
2641 MFT_TOO_FRAGMENTED = 0xC0000304,1807 MFT_TOO_FRAGMENTED = 0xC0000304,
2642
2643 /// Copy protection failure.1808 /// Copy protection failure.
2644 COPY_PROTECTION_FAILURE = 0xC0000305,1809 COPY_PROTECTION_FAILURE = 0xC0000305,
2645
2646 /// Copy protection error—DVD CSS Authentication failed.1810 /// Copy protection error—DVD CSS Authentication failed.
2647 CSS_AUTHENTICATION_FAILURE = 0xC0000306,1811 CSS_AUTHENTICATION_FAILURE = 0xC0000306,
2648
2649 /// Copy protection error—The specified sector does not contain a valid key.1812 /// Copy protection error—The specified sector does not contain a valid key.
2650 CSS_KEY_NOT_PRESENT = 0xC0000307,1813 CSS_KEY_NOT_PRESENT = 0xC0000307,
2651
2652 /// Copy protection error—DVD session key not established.1814 /// Copy protection error—DVD session key not established.
2653 CSS_KEY_NOT_ESTABLISHED = 0xC0000308,1815 CSS_KEY_NOT_ESTABLISHED = 0xC0000308,
2654
2655 /// Copy protection error—The read failed because the sector is encrypted.1816 /// Copy protection error—The read failed because the sector is encrypted.
2656 CSS_SCRAMBLED_SECTOR = 0xC0000309,1817 CSS_SCRAMBLED_SECTOR = 0xC0000309,
2657
2658 /// Copy protection error—The region of the specified DVD does not correspond to the region setting of the drive.1818 /// Copy protection error—The region of the specified DVD does not correspond to the region setting of the drive.
2659 CSS_REGION_MISMATCH = 0xC000030A,1819 CSS_REGION_MISMATCH = 0xC000030A,
2660
2661 /// Copy protection error—The region setting of the drive might be permanent.1820 /// Copy protection error—The region setting of the drive might be permanent.
2662 CSS_RESETS_EXHAUSTED = 0xC000030B,1821 CSS_RESETS_EXHAUSTED = 0xC000030B,
2663
2664 /// The Kerberos protocol encountered an error while validating the KDC certificate during smart card logon.1822 /// The Kerberos protocol encountered an error while validating the KDC certificate during smart card logon.
2665 /// There is more information in the system event log.1823 /// There is more information in the system event log.
2666 PKINIT_FAILURE = 0xC0000320,1824 PKINIT_FAILURE = 0xC0000320,
2667
2668 /// The Kerberos protocol encountered an error while attempting to use the smart card subsystem.1825 /// The Kerberos protocol encountered an error while attempting to use the smart card subsystem.
2669 SMARTCARD_SUBSYSTEM_FAILURE = 0xC0000321,1826 SMARTCARD_SUBSYSTEM_FAILURE = 0xC0000321,
2670
2671 /// The target server does not have acceptable Kerberos credentials.1827 /// The target server does not have acceptable Kerberos credentials.
2672 NO_KERB_KEY = 0xC0000322,1828 NO_KERB_KEY = 0xC0000322,
2673
2674 /// The transport determined that the remote system is down.1829 /// The transport determined that the remote system is down.
2675 HOST_DOWN = 0xC0000350,1830 HOST_DOWN = 0xC0000350,
2676
2677 /// An unsupported pre-authentication mechanism was presented to the Kerberos package.1831 /// An unsupported pre-authentication mechanism was presented to the Kerberos package.
2678 UNSUPPORTED_PREAUTH = 0xC0000351,1832 UNSUPPORTED_PREAUTH = 0xC0000351,
2679
2680 /// The encryption algorithm that is used on the source file needs a bigger key buffer than the one that is used on the destination file.1833 /// The encryption algorithm that is used on the source file needs a bigger key buffer than the one that is used on the destination file.
2681 EFS_ALG_BLOB_TOO_BIG = 0xC0000352,1834 EFS_ALG_BLOB_TOO_BIG = 0xC0000352,
2682
2683 /// An attempt to remove a processes DebugPort was made, but a port was not already associated with the process.1835 /// An attempt to remove a processes DebugPort was made, but a port was not already associated with the process.
2684 PORT_NOT_SET = 0xC0000353,1836 PORT_NOT_SET = 0xC0000353,
2685
2686 /// An attempt to do an operation on a debug port failed because the port is in the process of being deleted.1837 /// An attempt to do an operation on a debug port failed because the port is in the process of being deleted.
2687 DEBUGGER_INACTIVE = 0xC0000354,1838 DEBUGGER_INACTIVE = 0xC0000354,
2688
2689 /// This version of Windows is not compatible with the behavior version of the directory forest, domain, or domain controller.1839 /// This version of Windows is not compatible with the behavior version of the directory forest, domain, or domain controller.
2690 DS_VERSION_CHECK_FAILURE = 0xC0000355,1840 DS_VERSION_CHECK_FAILURE = 0xC0000355,
2691
2692 /// The specified event is currently not being audited.1841 /// The specified event is currently not being audited.
2693 AUDITING_DISABLED = 0xC0000356,1842 AUDITING_DISABLED = 0xC0000356,
2694
2695 /// The machine account was created prior to Windows NT 4.0 operating system. The account needs to be recreated.1843 /// The machine account was created prior to Windows NT 4.0 operating system. The account needs to be recreated.
2696 PRENT4_MACHINE_ACCOUNT = 0xC0000357,1844 PRENT4_MACHINE_ACCOUNT = 0xC0000357,
2697
2698 /// An account group cannot have a universal group as a member.1845 /// An account group cannot have a universal group as a member.
2699 DS_AG_CANT_HAVE_UNIVERSAL_MEMBER = 0xC0000358,1846 DS_AG_CANT_HAVE_UNIVERSAL_MEMBER = 0xC0000358,
2700
2701 /// The specified image file did not have the correct format; it appears to be a 32-bit Windows image.1847 /// The specified image file did not have the correct format; it appears to be a 32-bit Windows image.
2702 INVALID_IMAGE_WIN_32 = 0xC0000359,1848 INVALID_IMAGE_WIN_32 = 0xC0000359,
2703
2704 /// The specified image file did not have the correct format; it appears to be a 64-bit Windows image.1849 /// The specified image file did not have the correct format; it appears to be a 64-bit Windows image.
2705 INVALID_IMAGE_WIN_64 = 0xC000035A,1850 INVALID_IMAGE_WIN_64 = 0xC000035A,
2706
2707 /// The client's supplied SSPI channel bindings were incorrect.1851 /// The client's supplied SSPI channel bindings were incorrect.
2708 BAD_BINDINGS = 0xC000035B,1852 BAD_BINDINGS = 0xC000035B,
2709
2710 /// The client session has expired; so the client must re-authenticate to continue accessing the remote resources.1853 /// The client session has expired; so the client must re-authenticate to continue accessing the remote resources.
2711 NETWORK_SESSION_EXPIRED = 0xC000035C,1854 NETWORK_SESSION_EXPIRED = 0xC000035C,
2712
2713 /// The AppHelp dialog box canceled; thus preventing the application from starting.1855 /// The AppHelp dialog box canceled; thus preventing the application from starting.
2714 APPHELP_BLOCK = 0xC000035D,1856 APPHELP_BLOCK = 0xC000035D,
2715
2716 /// The SID filtering operation removed all SIDs.1857 /// The SID filtering operation removed all SIDs.
2717 ALL_SIDS_FILTERED = 0xC000035E,1858 ALL_SIDS_FILTERED = 0xC000035E,
2718
2719 /// The driver was not loaded because the system is starting in safe mode.1859 /// The driver was not loaded because the system is starting in safe mode.
2720 NOT_SAFE_MODE_DRIVER = 0xC000035F,1860 NOT_SAFE_MODE_DRIVER = 0xC000035F,
2721
2722 /// Access to %1 has been restricted by your Administrator by the default software restriction policy level.1861 /// Access to %1 has been restricted by your Administrator by the default software restriction policy level.
2723 ACCESS_DISABLED_BY_POLICY_DEFAULT = 0xC0000361,1862 ACCESS_DISABLED_BY_POLICY_DEFAULT = 0xC0000361,
2724
2725 /// Access to %1 has been restricted by your Administrator by location with policy rule %2 placed on path %3.1863 /// Access to %1 has been restricted by your Administrator by location with policy rule %2 placed on path %3.
2726 ACCESS_DISABLED_BY_POLICY_PATH = 0xC0000362,1864 ACCESS_DISABLED_BY_POLICY_PATH = 0xC0000362,
2727
2728 /// Access to %1 has been restricted by your Administrator by software publisher policy.1865 /// Access to %1 has been restricted by your Administrator by software publisher policy.
2729 ACCESS_DISABLED_BY_POLICY_PUBLISHER = 0xC0000363,1866 ACCESS_DISABLED_BY_POLICY_PUBLISHER = 0xC0000363,
2730
2731 /// Access to %1 has been restricted by your Administrator by policy rule %2.1867 /// Access to %1 has been restricted by your Administrator by policy rule %2.
2732 ACCESS_DISABLED_BY_POLICY_OTHER = 0xC0000364,1868 ACCESS_DISABLED_BY_POLICY_OTHER = 0xC0000364,
2733
2734 /// The driver was not loaded because it failed its initialization call.1869 /// The driver was not loaded because it failed its initialization call.
2735 FAILED_DRIVER_ENTRY = 0xC0000365,1870 FAILED_DRIVER_ENTRY = 0xC0000365,
2736
2737 /// The device encountered an error while applying power or reading the device configuration.1871 /// The device encountered an error while applying power or reading the device configuration.
2738 /// This might be caused by a failure of your hardware or by a poor connection.1872 /// This might be caused by a failure of your hardware or by a poor connection.
2739 DEVICE_ENUMERATION_ERROR = 0xC0000366,1873 DEVICE_ENUMERATION_ERROR = 0xC0000366,
2740
2741 /// The create operation failed because the name contained at least one mount point that resolves to a volume to which the specified device object is not attached.1874 /// The create operation failed because the name contained at least one mount point that resolves to a volume to which the specified device object is not attached.
2742 MOUNT_POINT_NOT_RESOLVED = 0xC0000368,1875 MOUNT_POINT_NOT_RESOLVED = 0xC0000368,
2743
2744 /// The device object parameter is either not a valid device object or is not attached to the volume that is specified by the file name.1876 /// The device object parameter is either not a valid device object or is not attached to the volume that is specified by the file name.
2745 INVALID_DEVICE_OBJECT_PARAMETER = 0xC0000369,1877 INVALID_DEVICE_OBJECT_PARAMETER = 0xC0000369,
2746
2747 /// A machine check error has occurred.1878 /// A machine check error has occurred.
2748 /// Check the system event log for additional information.1879 /// Check the system event log for additional information.
2749 MCA_OCCURED = 0xC000036A,1880 MCA_OCCURED = 0xC000036A,
2750
2751 /// Driver %2 has been blocked from loading.1881 /// Driver %2 has been blocked from loading.
2752 DRIVER_BLOCKED_CRITICAL = 0xC000036B,1882 DRIVER_BLOCKED_CRITICAL = 0xC000036B,
2753
2754 /// Driver %2 has been blocked from loading.1883 /// Driver %2 has been blocked from loading.
2755 DRIVER_BLOCKED = 0xC000036C,1884 DRIVER_BLOCKED = 0xC000036C,
2756
2757 /// There was error [%2] processing the driver database.1885 /// There was error [%2] processing the driver database.
2758 DRIVER_DATABASE_ERROR = 0xC000036D,1886 DRIVER_DATABASE_ERROR = 0xC000036D,
2759
2760 /// System hive size has exceeded its limit.1887 /// System hive size has exceeded its limit.
2761 SYSTEM_HIVE_TOO_LARGE = 0xC000036E,1888 SYSTEM_HIVE_TOO_LARGE = 0xC000036E,
2762
2763 /// A dynamic link library (DLL) referenced a module that was neither a DLL nor the process's executable image.1889 /// A dynamic link library (DLL) referenced a module that was neither a DLL nor the process's executable image.
2764 INVALID_IMPORT_OF_NON_DLL = 0xC000036F,1890 INVALID_IMPORT_OF_NON_DLL = 0xC000036F,
2765
2766 /// The local account store does not contain secret material for the specified account.1891 /// The local account store does not contain secret material for the specified account.
2767 NO_SECRETS = 0xC0000371,1892 NO_SECRETS = 0xC0000371,
2768
2769 /// Access to %1 has been restricted by your Administrator by policy rule %2.1893 /// Access to %1 has been restricted by your Administrator by policy rule %2.
2770 ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY = 0xC0000372,1894 ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY = 0xC0000372,
2771
2772 /// The system was not able to allocate enough memory to perform a stack switch.1895 /// The system was not able to allocate enough memory to perform a stack switch.
2773 FAILED_STACK_SWITCH = 0xC0000373,1896 FAILED_STACK_SWITCH = 0xC0000373,
2774
2775 /// A heap has been corrupted.1897 /// A heap has been corrupted.
2776 HEAP_CORRUPTION = 0xC0000374,1898 HEAP_CORRUPTION = 0xC0000374,
2777
2778 /// An incorrect PIN was presented to the smart card.1899 /// An incorrect PIN was presented to the smart card.
2779 SMARTCARD_WRONG_PIN = 0xC0000380,1900 SMARTCARD_WRONG_PIN = 0xC0000380,
2780
2781 /// The smart card is blocked.1901 /// The smart card is blocked.
2782 SMARTCARD_CARD_BLOCKED = 0xC0000381,1902 SMARTCARD_CARD_BLOCKED = 0xC0000381,
2783
2784 /// No PIN was presented to the smart card.1903 /// No PIN was presented to the smart card.
2785 SMARTCARD_CARD_NOT_AUTHENTICATED = 0xC0000382,1904 SMARTCARD_CARD_NOT_AUTHENTICATED = 0xC0000382,
2786
2787 /// No smart card is available.1905 /// No smart card is available.
2788 SMARTCARD_NO_CARD = 0xC0000383,1906 SMARTCARD_NO_CARD = 0xC0000383,
2789
2790 /// The requested key container does not exist on the smart card.1907 /// The requested key container does not exist on the smart card.
2791 SMARTCARD_NO_KEY_CONTAINER = 0xC0000384,1908 SMARTCARD_NO_KEY_CONTAINER = 0xC0000384,
2792
2793 /// The requested certificate does not exist on the smart card.1909 /// The requested certificate does not exist on the smart card.
2794 SMARTCARD_NO_CERTIFICATE = 0xC0000385,1910 SMARTCARD_NO_CERTIFICATE = 0xC0000385,
2795
2796 /// The requested keyset does not exist.1911 /// The requested keyset does not exist.
2797 SMARTCARD_NO_KEYSET = 0xC0000386,1912 SMARTCARD_NO_KEYSET = 0xC0000386,
2798
2799 /// A communication error with the smart card has been detected.1913 /// A communication error with the smart card has been detected.
2800 SMARTCARD_IO_ERROR = 0xC0000387,1914 SMARTCARD_IO_ERROR = 0xC0000387,
2801
2802 /// The system detected a possible attempt to compromise security.1915 /// The system detected a possible attempt to compromise security.
2803 /// Ensure that you can contact the server that authenticated you.1916 /// Ensure that you can contact the server that authenticated you.
2804 DOWNGRADE_DETECTED = 0xC0000388,1917 DOWNGRADE_DETECTED = 0xC0000388,
2805
2806 /// The smart card certificate used for authentication has been revoked. Contact your system administrator.1918 /// The smart card certificate used for authentication has been revoked. Contact your system administrator.
2807 /// There might be additional information in the event log.1919 /// There might be additional information in the event log.
2808 SMARTCARD_CERT_REVOKED = 0xC0000389,1920 SMARTCARD_CERT_REVOKED = 0xC0000389,
2809
2810 /// An untrusted certificate authority was detected while processing the smart card certificate that is used for authentication. Contact your system administrator.1921 /// An untrusted certificate authority was detected while processing the smart card certificate that is used for authentication. Contact your system administrator.
2811 ISSUING_CA_UNTRUSTED = 0xC000038A,1922 ISSUING_CA_UNTRUSTED = 0xC000038A,
2812
2813 /// The revocation status of the smart card certificate that is used for authentication could not be determined. Contact your system administrator.1923 /// The revocation status of the smart card certificate that is used for authentication could not be determined. Contact your system administrator.
2814 REVOCATION_OFFLINE_C = 0xC000038B,1924 REVOCATION_OFFLINE_C = 0xC000038B,
2815
2816 /// The smart card certificate used for authentication was not trusted. Contact your system administrator.1925 /// The smart card certificate used for authentication was not trusted. Contact your system administrator.
2817 PKINIT_CLIENT_FAILURE = 0xC000038C,1926 PKINIT_CLIENT_FAILURE = 0xC000038C,
2818
2819 /// The smart card certificate used for authentication has expired. Contact your system administrator.1927 /// The smart card certificate used for authentication has expired. Contact your system administrator.
2820 SMARTCARD_CERT_EXPIRED = 0xC000038D,1928 SMARTCARD_CERT_EXPIRED = 0xC000038D,
2821
2822 /// The driver could not be loaded because a previous version of the driver is still in memory.1929 /// The driver could not be loaded because a previous version of the driver is still in memory.
2823 DRIVER_FAILED_PRIOR_UNLOAD = 0xC000038E,1930 DRIVER_FAILED_PRIOR_UNLOAD = 0xC000038E,
2824
2825 /// The smart card provider could not perform the action because the context was acquired as silent.1931 /// The smart card provider could not perform the action because the context was acquired as silent.
2826 SMARTCARD_SILENT_CONTEXT = 0xC000038F,1932 SMARTCARD_SILENT_CONTEXT = 0xC000038F,
2827
2828 /// The delegated trust creation quota of the current user has been exceeded.1933 /// The delegated trust creation quota of the current user has been exceeded.
2829 PER_USER_TRUST_QUOTA_EXCEEDED = 0xC0000401,1934 PER_USER_TRUST_QUOTA_EXCEEDED = 0xC0000401,
2830
2831 /// The total delegated trust creation quota has been exceeded.1935 /// The total delegated trust creation quota has been exceeded.
2832 ALL_USER_TRUST_QUOTA_EXCEEDED = 0xC0000402,1936 ALL_USER_TRUST_QUOTA_EXCEEDED = 0xC0000402,
2833
2834 /// The delegated trust deletion quota of the current user has been exceeded.1937 /// The delegated trust deletion quota of the current user has been exceeded.
2835 USER_DELETE_TRUST_QUOTA_EXCEEDED = 0xC0000403,1938 USER_DELETE_TRUST_QUOTA_EXCEEDED = 0xC0000403,
2836
2837 /// The requested name already exists as a unique identifier.1939 /// The requested name already exists as a unique identifier.
2838 DS_NAME_NOT_UNIQUE = 0xC0000404,1940 DS_NAME_NOT_UNIQUE = 0xC0000404,
2839
2840 /// The requested object has a non-unique identifier and cannot be retrieved.1941 /// The requested object has a non-unique identifier and cannot be retrieved.
2841 DS_DUPLICATE_ID_FOUND = 0xC0000405,1942 DS_DUPLICATE_ID_FOUND = 0xC0000405,
2842
2843 /// The group cannot be converted due to attribute restrictions on the requested group type.1943 /// The group cannot be converted due to attribute restrictions on the requested group type.
2844 DS_GROUP_CONVERSION_ERROR = 0xC0000406,1944 DS_GROUP_CONVERSION_ERROR = 0xC0000406,
2845
2846 /// {Volume Shadow Copy Service} Wait while the Volume Shadow Copy Service prepares volume %hs for hibernation.1945 /// {Volume Shadow Copy Service} Wait while the Volume Shadow Copy Service prepares volume %hs for hibernation.
2847 VOLSNAP_PREPARE_HIBERNATE = 0xC0000407,1946 VOLSNAP_PREPARE_HIBERNATE = 0xC0000407,
2848
2849 /// Kerberos sub-protocol User2User is required.1947 /// Kerberos sub-protocol User2User is required.
2850 USER2USER_REQUIRED = 0xC0000408,1948 USER2USER_REQUIRED = 0xC0000408,
2851
2852 /// The system detected an overrun of a stack-based buffer in this application.1949 /// The system detected an overrun of a stack-based buffer in this application.
2853 /// This overrun could potentially allow a malicious user to gain control of this application.1950 /// This overrun could potentially allow a malicious user to gain control of this application.
2854 STACK_BUFFER_OVERRUN = 0xC0000409,1951 STACK_BUFFER_OVERRUN = 0xC0000409,
2855
2856 /// The Kerberos subsystem encountered an error.1952 /// The Kerberos subsystem encountered an error.
2857 /// A service for user protocol request was made against a domain controller which does not support service for user.1953 /// A service for user protocol request was made against a domain controller which does not support service for user.
2858 NO_S4U_PROT_SUPPORT = 0xC000040A,1954 NO_S4U_PROT_SUPPORT = 0xC000040A,
2859
2860 /// An attempt was made by this server to make a Kerberos constrained delegation request for a target that is outside the server realm.1955 /// An attempt was made by this server to make a Kerberos constrained delegation request for a target that is outside the server realm.
2861 /// This action is not supported and the resulting error indicates a misconfiguration on the allowed-to-delegate-to list for this server. Contact your administrator.1956 /// This action is not supported and the resulting error indicates a misconfiguration on the allowed-to-delegate-to list for this server. Contact your administrator.
2862 CROSSREALM_DELEGATION_FAILURE = 0xC000040B,1957 CROSSREALM_DELEGATION_FAILURE = 0xC000040B,
2863
2864 /// The revocation status of the domain controller certificate used for smart card authentication could not be determined.1958 /// The revocation status of the domain controller certificate used for smart card authentication could not be determined.
2865 /// There is additional information in the system event log. Contact your system administrator.1959 /// There is additional information in the system event log. Contact your system administrator.
2866 REVOCATION_OFFLINE_KDC = 0xC000040C,1960 REVOCATION_OFFLINE_KDC = 0xC000040C,
2867
2868 /// An untrusted certificate authority was detected while processing the domain controller certificate used for authentication.1961 /// An untrusted certificate authority was detected while processing the domain controller certificate used for authentication.
2869 /// There is additional information in the system event log. Contact your system administrator.1962 /// There is additional information in the system event log. Contact your system administrator.
2870 ISSUING_CA_UNTRUSTED_KDC = 0xC000040D,1963 ISSUING_CA_UNTRUSTED_KDC = 0xC000040D,
2871
2872 /// The domain controller certificate used for smart card logon has expired.1964 /// The domain controller certificate used for smart card logon has expired.
2873 /// Contact your system administrator with the contents of your system event log.1965 /// Contact your system administrator with the contents of your system event log.
2874 KDC_CERT_EXPIRED = 0xC000040E,1966 KDC_CERT_EXPIRED = 0xC000040E,
2875
2876 /// The domain controller certificate used for smart card logon has been revoked.1967 /// The domain controller certificate used for smart card logon has been revoked.
2877 /// Contact your system administrator with the contents of your system event log.1968 /// Contact your system administrator with the contents of your system event log.
2878 KDC_CERT_REVOKED = 0xC000040F,1969 KDC_CERT_REVOKED = 0xC000040F,
2879
2880 /// Data present in one of the parameters is more than the function can operate on.1970 /// Data present in one of the parameters is more than the function can operate on.
2881 PARAMETER_QUOTA_EXCEEDED = 0xC0000410,1971 PARAMETER_QUOTA_EXCEEDED = 0xC0000410,
2882
2883 /// The system has failed to hibernate (The error code is %hs).1972 /// The system has failed to hibernate (The error code is %hs).
2884 /// Hibernation will be disabled until the system is restarted.1973 /// Hibernation will be disabled until the system is restarted.
2885 HIBERNATION_FAILURE = 0xC0000411,1974 HIBERNATION_FAILURE = 0xC0000411,
2886
2887 /// An attempt to delay-load a .dll or get a function address in a delay-loaded .dll failed.1975 /// An attempt to delay-load a .dll or get a function address in a delay-loaded .dll failed.
2888 DELAY_LOAD_FAILED = 0xC0000412,1976 DELAY_LOAD_FAILED = 0xC0000412,
2889
2890 /// Logon Failure: The machine you are logging onto is protected by an authentication firewall.1977 /// Logon Failure: The machine you are logging onto is protected by an authentication firewall.
2891 /// The specified account is not allowed to authenticate to the machine.1978 /// The specified account is not allowed to authenticate to the machine.
2892 AUTHENTICATION_FIREWALL_FAILED = 0xC0000413,1979 AUTHENTICATION_FIREWALL_FAILED = 0xC0000413,
2893
2894 /// %hs is a 16-bit application. You do not have permissions to execute 16-bit applications.1980 /// %hs is a 16-bit application. You do not have permissions to execute 16-bit applications.
2895 /// Check your permissions with your system administrator.1981 /// Check your permissions with your system administrator.
2896 VDM_DISALLOWED = 0xC0000414,1982 VDM_DISALLOWED = 0xC0000414,
2897
2898 /// {Display Driver Stopped Responding} The %hs display driver has stopped working normally.1983 /// {Display Driver Stopped Responding} The %hs display driver has stopped working normally.
2899 /// Save your work and reboot the system to restore full display functionality.1984 /// Save your work and reboot the system to restore full display functionality.
2900 /// The next time you reboot the machine a dialog will be displayed giving you a chance to report this failure to Microsoft.1985 /// The next time you reboot the machine a dialog will be displayed giving you a chance to report this failure to Microsoft.
2901 HUNG_DISPLAY_DRIVER_THREAD = 0xC0000415,1986 HUNG_DISPLAY_DRIVER_THREAD = 0xC0000415,
2902
2903 /// The Desktop heap encountered an error while allocating session memory.1987 /// The Desktop heap encountered an error while allocating session memory.
2904 /// There is more information in the system event log.1988 /// There is more information in the system event log.
2905 INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE = 0xC0000416,1989 INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE = 0xC0000416,
2906
2907 /// An invalid parameter was passed to a C runtime function.1990 /// An invalid parameter was passed to a C runtime function.
2908 INVALID_CRUNTIME_PARAMETER = 0xC0000417,1991 INVALID_CRUNTIME_PARAMETER = 0xC0000417,
2909
2910 /// The authentication failed because NTLM was blocked.1992 /// The authentication failed because NTLM was blocked.
2911 NTLM_BLOCKED = 0xC0000418,1993 NTLM_BLOCKED = 0xC0000418,
2912
2913 /// The source object's SID already exists in destination forest.1994 /// The source object's SID already exists in destination forest.
2914 DS_SRC_SID_EXISTS_IN_FOREST = 0xC0000419,1995 DS_SRC_SID_EXISTS_IN_FOREST = 0xC0000419,
2915
2916 /// The domain name of the trusted domain already exists in the forest.1996 /// The domain name of the trusted domain already exists in the forest.
2917 DS_DOMAIN_NAME_EXISTS_IN_FOREST = 0xC000041A,1997 DS_DOMAIN_NAME_EXISTS_IN_FOREST = 0xC000041A,
2918
2919 /// The flat name of the trusted domain already exists in the forest.1998 /// The flat name of the trusted domain already exists in the forest.
2920 DS_FLAT_NAME_EXISTS_IN_FOREST = 0xC000041B,1999 DS_FLAT_NAME_EXISTS_IN_FOREST = 0xC000041B,
2921
2922 /// The User Principal Name (UPN) is invalid.2000 /// The User Principal Name (UPN) is invalid.
2923 INVALID_USER_PRINCIPAL_NAME = 0xC000041C,2001 INVALID_USER_PRINCIPAL_NAME = 0xC000041C,
2924
2925 /// There has been an assertion failure.2002 /// There has been an assertion failure.
2926 ASSERTION_FAILURE = 0xC0000420,2003 ASSERTION_FAILURE = 0xC0000420,
2927
2928 /// Application verifier has found an error in the current process.2004 /// Application verifier has found an error in the current process.
2929 VERIFIER_STOP = 0xC0000421,2005 VERIFIER_STOP = 0xC0000421,
2930
2931 /// A user mode unwind is in progress.2006 /// A user mode unwind is in progress.
2932 CALLBACK_POP_STACK = 0xC0000423,2007 CALLBACK_POP_STACK = 0xC0000423,
2933
2934 /// %2 has been blocked from loading due to incompatibility with this system.2008 /// %2 has been blocked from loading due to incompatibility with this system.
2935 /// Contact your software vendor for a compatible version of the driver.2009 /// Contact your software vendor for a compatible version of the driver.
2936 INCOMPATIBLE_DRIVER_BLOCKED = 0xC0000424,2010 INCOMPATIBLE_DRIVER_BLOCKED = 0xC0000424,
2937
2938 /// Illegal operation attempted on a registry key which has already been unloaded.2011 /// Illegal operation attempted on a registry key which has already been unloaded.
2939 HIVE_UNLOADED = 0xC0000425,2012 HIVE_UNLOADED = 0xC0000425,
2940
2941 /// Compression is disabled for this volume.2013 /// Compression is disabled for this volume.
2942 COMPRESSION_DISABLED = 0xC0000426,2014 COMPRESSION_DISABLED = 0xC0000426,
2943
2944 /// The requested operation could not be completed due to a file system limitation.2015 /// The requested operation could not be completed due to a file system limitation.
2945 FILE_SYSTEM_LIMITATION = 0xC0000427,2016 FILE_SYSTEM_LIMITATION = 0xC0000427,
2946
2947 /// The hash for image %hs cannot be found in the system catalogs.2017 /// The hash for image %hs cannot be found in the system catalogs.
2948 /// The image is likely corrupt or the victim of tampering.2018 /// The image is likely corrupt or the victim of tampering.
2949 INVALID_IMAGE_HASH = 0xC0000428,2019 INVALID_IMAGE_HASH = 0xC0000428,
2950
2951 /// The implementation is not capable of performing the request.2020 /// The implementation is not capable of performing the request.
2952 NOT_CAPABLE = 0xC0000429,2021 NOT_CAPABLE = 0xC0000429,
2953
2954 /// The requested operation is out of order with respect to other operations.2022 /// The requested operation is out of order with respect to other operations.
2955 REQUEST_OUT_OF_SEQUENCE = 0xC000042A,2023 REQUEST_OUT_OF_SEQUENCE = 0xC000042A,
2956
2957 /// An operation attempted to exceed an implementation-defined limit.2024 /// An operation attempted to exceed an implementation-defined limit.
2958 IMPLEMENTATION_LIMIT = 0xC000042B,2025 IMPLEMENTATION_LIMIT = 0xC000042B,
2959
2960 /// The requested operation requires elevation.2026 /// The requested operation requires elevation.
2961 ELEVATION_REQUIRED = 0xC000042C,2027 ELEVATION_REQUIRED = 0xC000042C,
2962
2963 /// The required security context does not exist.2028 /// The required security context does not exist.
2964 NO_SECURITY_CONTEXT = 0xC000042D,2029 NO_SECURITY_CONTEXT = 0xC000042D,
2965
2966 /// The PKU2U protocol encountered an error while attempting to utilize the associated certificates.2030 /// The PKU2U protocol encountered an error while attempting to utilize the associated certificates.
2967 PKU2U_CERT_FAILURE = 0xC000042E,2031 PKU2U_CERT_FAILURE = 0xC000042E,
2968
2969 /// The operation was attempted beyond the valid data length of the file.2032 /// The operation was attempted beyond the valid data length of the file.
2970 BEYOND_VDL = 0xC0000432,2033 BEYOND_VDL = 0xC0000432,
2971
2972 /// The attempted write operation encountered a write already in progress for some portion of the range.2034 /// The attempted write operation encountered a write already in progress for some portion of the range.
2973 ENCOUNTERED_WRITE_IN_PROGRESS = 0xC0000433,2035 ENCOUNTERED_WRITE_IN_PROGRESS = 0xC0000433,
2974
2975 /// The page fault mappings changed in the middle of processing a fault so the operation must be retried.2036 /// The page fault mappings changed in the middle of processing a fault so the operation must be retried.
2976 PTE_CHANGED = 0xC0000434,2037 PTE_CHANGED = 0xC0000434,
2977
2978 /// The attempt to purge this file from memory failed to purge some or all the data from memory.2038 /// The attempt to purge this file from memory failed to purge some or all the data from memory.
2979 PURGE_FAILED = 0xC0000435,2039 PURGE_FAILED = 0xC0000435,
2980
2981 /// The requested credential requires confirmation.2040 /// The requested credential requires confirmation.
2982 CRED_REQUIRES_CONFIRMATION = 0xC0000440,2041 CRED_REQUIRES_CONFIRMATION = 0xC0000440,
2983
2984 /// The remote server sent an invalid response for a file being opened with Client Side Encryption.2042 /// The remote server sent an invalid response for a file being opened with Client Side Encryption.
2985 CS_ENCRYPTION_INVALID_SERVER_RESPONSE = 0xC0000441,2043 CS_ENCRYPTION_INVALID_SERVER_RESPONSE = 0xC0000441,
2986
2987 /// Client Side Encryption is not supported by the remote server even though it claims to support it.2044 /// Client Side Encryption is not supported by the remote server even though it claims to support it.
2988 CS_ENCRYPTION_UNSUPPORTED_SERVER = 0xC0000442,2045 CS_ENCRYPTION_UNSUPPORTED_SERVER = 0xC0000442,
2989
2990 /// File is encrypted and should be opened in Client Side Encryption mode.2046 /// File is encrypted and should be opened in Client Side Encryption mode.
2991 CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE = 0xC0000443,2047 CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE = 0xC0000443,
2992
2993 /// A new encrypted file is being created and a $EFS needs to be provided.2048 /// A new encrypted file is being created and a $EFS needs to be provided.
2994 CS_ENCRYPTION_NEW_ENCRYPTED_FILE = 0xC0000444,2049 CS_ENCRYPTION_NEW_ENCRYPTED_FILE = 0xC0000444,
2995
2996 /// The SMB client requested a CSE FSCTL on a non-CSE file.2050 /// The SMB client requested a CSE FSCTL on a non-CSE file.
2997 CS_ENCRYPTION_FILE_NOT_CSE = 0xC0000445,2051 CS_ENCRYPTION_FILE_NOT_CSE = 0xC0000445,
2998
2999 /// Indicates a particular Security ID cannot be assigned as the label of an object.2052 /// Indicates a particular Security ID cannot be assigned as the label of an object.
3000 INVALID_LABEL = 0xC0000446,2053 INVALID_LABEL = 0xC0000446,
3001
3002 /// The process hosting the driver for this device has terminated.2054 /// The process hosting the driver for this device has terminated.
3003 DRIVER_PROCESS_TERMINATED = 0xC0000450,2055 DRIVER_PROCESS_TERMINATED = 0xC0000450,
3004
3005 /// The requested system device cannot be identified due to multiple indistinguishable devices potentially matching the identification criteria.2056 /// The requested system device cannot be identified due to multiple indistinguishable devices potentially matching the identification criteria.
3006 AMBIGUOUS_SYSTEM_DEVICE = 0xC0000451,2057 AMBIGUOUS_SYSTEM_DEVICE = 0xC0000451,
3007
3008 /// The requested system device cannot be found.2058 /// The requested system device cannot be found.
3009 SYSTEM_DEVICE_NOT_FOUND = 0xC0000452,2059 SYSTEM_DEVICE_NOT_FOUND = 0xC0000452,
3010
3011 /// This boot application must be restarted.2060 /// This boot application must be restarted.
3012 RESTART_BOOT_APPLICATION = 0xC0000453,2061 RESTART_BOOT_APPLICATION = 0xC0000453,
3013
3014 /// Insufficient NVRAM resources exist to complete the API. A reboot might be required.2062 /// Insufficient NVRAM resources exist to complete the API. A reboot might be required.
3015 INSUFFICIENT_NVRAM_RESOURCES = 0xC0000454,2063 INSUFFICIENT_NVRAM_RESOURCES = 0xC0000454,
3016
3017 /// No ranges for the specified operation were able to be processed.2064 /// No ranges for the specified operation were able to be processed.
3018 NO_RANGES_PROCESSED = 0xC0000460,2065 NO_RANGES_PROCESSED = 0xC0000460,
3019
3020 /// The storage device does not support Offload Write.2066 /// The storage device does not support Offload Write.
3021 DEVICE_FEATURE_NOT_SUPPORTED = 0xC0000463,2067 DEVICE_FEATURE_NOT_SUPPORTED = 0xC0000463,
3022
3023 /// Data cannot be moved because the source device cannot communicate with the destination device.2068 /// Data cannot be moved because the source device cannot communicate with the destination device.
3024 DEVICE_UNREACHABLE = 0xC0000464,2069 DEVICE_UNREACHABLE = 0xC0000464,
3025
3026 /// The token representing the data is invalid or expired.2070 /// The token representing the data is invalid or expired.
3027 INVALID_TOKEN = 0xC0000465,2071 INVALID_TOKEN = 0xC0000465,
3028
3029 /// The file server is temporarily unavailable.2072 /// The file server is temporarily unavailable.
3030 SERVER_UNAVAILABLE = 0xC0000466,2073 SERVER_UNAVAILABLE = 0xC0000466,
3031
3032 /// The specified task name is invalid.2074 /// The specified task name is invalid.
3033 INVALID_TASK_NAME = 0xC0000500,2075 INVALID_TASK_NAME = 0xC0000500,
3034
3035 /// The specified task index is invalid.2076 /// The specified task index is invalid.
3036 INVALID_TASK_INDEX = 0xC0000501,2077 INVALID_TASK_INDEX = 0xC0000501,
3037
3038 /// The specified thread is already joining a task.2078 /// The specified thread is already joining a task.
3039 THREAD_ALREADY_IN_TASK = 0xC0000502,2079 THREAD_ALREADY_IN_TASK = 0xC0000502,
3040
3041 /// A callback has requested to bypass native code.2080 /// A callback has requested to bypass native code.
3042 CALLBACK_BYPASS = 0xC0000503,2081 CALLBACK_BYPASS = 0xC0000503,
3043
3044 /// A fail fast exception occurred.2082 /// A fail fast exception occurred.
3045 /// Exception handlers will not be invoked and the process will be terminated immediately.2083 /// Exception handlers will not be invoked and the process will be terminated immediately.
3046 FAIL_FAST_EXCEPTION = 0xC0000602,2084 FAIL_FAST_EXCEPTION = 0xC0000602,
3047
3048 /// Windows cannot verify the digital signature for this file.2085 /// Windows cannot verify the digital signature for this file.
3049 /// The signing certificate for this file has been revoked.2086 /// The signing certificate for this file has been revoked.
3050 IMAGE_CERT_REVOKED = 0xC0000603,2087 IMAGE_CERT_REVOKED = 0xC0000603,
3051
3052 /// The ALPC port is closed.2088 /// The ALPC port is closed.
3053 PORT_CLOSED = 0xC0000700,2089 PORT_CLOSED = 0xC0000700,
3054
3055 /// The ALPC message requested is no longer available.2090 /// The ALPC message requested is no longer available.
3056 MESSAGE_LOST = 0xC0000701,2091 MESSAGE_LOST = 0xC0000701,
3057
3058 /// The ALPC message supplied is invalid.2092 /// The ALPC message supplied is invalid.
3059 INVALID_MESSAGE = 0xC0000702,2093 INVALID_MESSAGE = 0xC0000702,
3060
3061 /// The ALPC message has been canceled.2094 /// The ALPC message has been canceled.
3062 REQUEST_CANCELED = 0xC0000703,2095 REQUEST_CANCELED = 0xC0000703,
3063
3064 /// Invalid recursive dispatch attempt.2096 /// Invalid recursive dispatch attempt.
3065 RECURSIVE_DISPATCH = 0xC0000704,2097 RECURSIVE_DISPATCH = 0xC0000704,
3066
3067 /// No receive buffer has been supplied in a synchronous request.2098 /// No receive buffer has been supplied in a synchronous request.
3068 LPC_RECEIVE_BUFFER_EXPECTED = 0xC0000705,2099 LPC_RECEIVE_BUFFER_EXPECTED = 0xC0000705,
3069
3070 /// The connection port is used in an invalid context.2100 /// The connection port is used in an invalid context.
3071 LPC_INVALID_CONNECTION_USAGE = 0xC0000706,2101 LPC_INVALID_CONNECTION_USAGE = 0xC0000706,
3072
3073 /// The ALPC port does not accept new request messages.2102 /// The ALPC port does not accept new request messages.
3074 LPC_REQUESTS_NOT_ALLOWED = 0xC0000707,2103 LPC_REQUESTS_NOT_ALLOWED = 0xC0000707,
3075
3076 /// The resource requested is already in use.2104 /// The resource requested is already in use.
3077 RESOURCE_IN_USE = 0xC0000708,2105 RESOURCE_IN_USE = 0xC0000708,
3078
3079 /// The hardware has reported an uncorrectable memory error.2106 /// The hardware has reported an uncorrectable memory error.
3080 HARDWARE_MEMORY_ERROR = 0xC0000709,2107 HARDWARE_MEMORY_ERROR = 0xC0000709,
3081
3082 /// Status 0x%08x was returned, waiting on handle 0x%x for wait 0x%p, in waiter 0x%p.2108 /// Status 0x%08x was returned, waiting on handle 0x%x for wait 0x%p, in waiter 0x%p.
3083 THREADPOOL_HANDLE_EXCEPTION = 0xC000070A,2109 THREADPOOL_HANDLE_EXCEPTION = 0xC000070A,
3084
3085 /// After a callback to 0x%p(0x%p), a completion call to Set event(0x%p) failed with status 0x%08x.2110 /// After a callback to 0x%p(0x%p), a completion call to Set event(0x%p) failed with status 0x%08x.
3086 THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED = 0xC000070B,2111 THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED = 0xC000070B,
3087
3088 /// After a callback to 0x%p(0x%p), a completion call to ReleaseSemaphore(0x%p, %d) failed with status 0x%08x.2112 /// After a callback to 0x%p(0x%p), a completion call to ReleaseSemaphore(0x%p, %d) failed with status 0x%08x.
3089 THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED = 0xC000070C,2113 THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED = 0xC000070C,
3090
3091 /// After a callback to 0x%p(0x%p), a completion call to ReleaseMutex(%p) failed with status 0x%08x.2114 /// After a callback to 0x%p(0x%p), a completion call to ReleaseMutex(%p) failed with status 0x%08x.
3092 THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED = 0xC000070D,2115 THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED = 0xC000070D,
3093
3094 /// After a callback to 0x%p(0x%p), a completion call to FreeLibrary(%p) failed with status 0x%08x.2116 /// After a callback to 0x%p(0x%p), a completion call to FreeLibrary(%p) failed with status 0x%08x.
3095 THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED = 0xC000070E,2117 THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED = 0xC000070E,
3096
3097 /// The thread pool 0x%p was released while a thread was posting a callback to 0x%p(0x%p) to it.2118 /// The thread pool 0x%p was released while a thread was posting a callback to 0x%p(0x%p) to it.
3098 THREADPOOL_RELEASED_DURING_OPERATION = 0xC000070F,2119 THREADPOOL_RELEASED_DURING_OPERATION = 0xC000070F,
3099
3100 /// A thread pool worker thread is impersonating a client, after a callback to 0x%p(0x%p).2120 /// A thread pool worker thread is impersonating a client, after a callback to 0x%p(0x%p).
3101 /// This is unexpected, indicating that the callback is missing a call to revert the impersonation.2121 /// This is unexpected, indicating that the callback is missing a call to revert the impersonation.
3102 CALLBACK_RETURNED_WHILE_IMPERSONATING = 0xC0000710,2122 CALLBACK_RETURNED_WHILE_IMPERSONATING = 0xC0000710,
3103
3104 /// A thread pool worker thread is impersonating a client, after executing an APC.2123 /// A thread pool worker thread is impersonating a client, after executing an APC.
3105 /// This is unexpected, indicating that the APC is missing a call to revert the impersonation.2124 /// This is unexpected, indicating that the APC is missing a call to revert the impersonation.
3106 APC_RETURNED_WHILE_IMPERSONATING = 0xC0000711,2125 APC_RETURNED_WHILE_IMPERSONATING = 0xC0000711,
3107
3108 /// Either the target process, or the target thread's containing process, is a protected process.2126 /// Either the target process, or the target thread's containing process, is a protected process.
3109 PROCESS_IS_PROTECTED = 0xC0000712,2127 PROCESS_IS_PROTECTED = 0xC0000712,
3110
3111 /// A thread is getting dispatched with MCA EXCEPTION because of MCA.2128 /// A thread is getting dispatched with MCA EXCEPTION because of MCA.
3112 MCA_EXCEPTION = 0xC0000713,2129 MCA_EXCEPTION = 0xC0000713,
3113
3114 /// The client certificate account mapping is not unique.2130 /// The client certificate account mapping is not unique.
3115 CERTIFICATE_MAPPING_NOT_UNIQUE = 0xC0000714,2131 CERTIFICATE_MAPPING_NOT_UNIQUE = 0xC0000714,
3116
3117 /// The symbolic link cannot be followed because its type is disabled.2132 /// The symbolic link cannot be followed because its type is disabled.
3118 SYMLINK_CLASS_DISABLED = 0xC0000715,2133 SYMLINK_CLASS_DISABLED = 0xC0000715,
3119
3120 /// Indicates that the specified string is not valid for IDN normalization.2134 /// Indicates that the specified string is not valid for IDN normalization.
3121 INVALID_IDN_NORMALIZATION = 0xC0000716,2135 INVALID_IDN_NORMALIZATION = 0xC0000716,
3122
3123 /// No mapping for the Unicode character exists in the target multi-byte code page.2136 /// No mapping for the Unicode character exists in the target multi-byte code page.
3124 NO_UNICODE_TRANSLATION = 0xC0000717,2137 NO_UNICODE_TRANSLATION = 0xC0000717,
3125
3126 /// The provided callback is already registered.2138 /// The provided callback is already registered.
3127 ALREADY_REGISTERED = 0xC0000718,2139 ALREADY_REGISTERED = 0xC0000718,
3128
3129 /// The provided context did not match the target.2140 /// The provided context did not match the target.
3130 CONTEXT_MISMATCH = 0xC0000719,2141 CONTEXT_MISMATCH = 0xC0000719,
3131
3132 /// The specified port already has a completion list.2142 /// The specified port already has a completion list.
3133 PORT_ALREADY_HAS_COMPLETION_LIST = 0xC000071A,2143 PORT_ALREADY_HAS_COMPLETION_LIST = 0xC000071A,
3134
3135 /// A threadpool worker thread entered a callback at thread base priority 0x%x and exited at priority 0x%x.2144 /// A threadpool worker thread entered a callback at thread base priority 0x%x and exited at priority 0x%x.
3136 /// This is unexpected, indicating that the callback missed restoring the priority.2145 /// This is unexpected, indicating that the callback missed restoring the priority.
3137 CALLBACK_RETURNED_THREAD_PRIORITY = 0xC000071B,2146 CALLBACK_RETURNED_THREAD_PRIORITY = 0xC000071B,
3138
3139 /// An invalid thread, handle %p, is specified for this operation.2147 /// An invalid thread, handle %p, is specified for this operation.
3140 /// Possibly, a threadpool worker thread was specified.2148 /// Possibly, a threadpool worker thread was specified.
3141 INVALID_THREAD = 0xC000071C,2149 INVALID_THREAD = 0xC000071C,
3142
3143 /// A threadpool worker thread entered a callback, which left transaction state.2150 /// A threadpool worker thread entered a callback, which left transaction state.
3144 /// This is unexpected, indicating that the callback missed clearing the transaction.2151 /// This is unexpected, indicating that the callback missed clearing the transaction.
3145 CALLBACK_RETURNED_TRANSACTION = 0xC000071D,2152 CALLBACK_RETURNED_TRANSACTION = 0xC000071D,
3146
3147 /// A threadpool worker thread entered a callback, which left the loader lock held.2153 /// A threadpool worker thread entered a callback, which left the loader lock held.
3148 /// This is unexpected, indicating that the callback missed releasing the lock.2154 /// This is unexpected, indicating that the callback missed releasing the lock.
3149 CALLBACK_RETURNED_LDR_LOCK = 0xC000071E,2155 CALLBACK_RETURNED_LDR_LOCK = 0xC000071E,
3150
3151 /// A threadpool worker thread entered a callback, which left with preferred languages set.2156 /// A threadpool worker thread entered a callback, which left with preferred languages set.
3152 /// This is unexpected, indicating that the callback missed clearing them.2157 /// This is unexpected, indicating that the callback missed clearing them.
3153 CALLBACK_RETURNED_LANG = 0xC000071F,2158 CALLBACK_RETURNED_LANG = 0xC000071F,
3154
3155 /// A threadpool worker thread entered a callback, which left with background priorities set.2159 /// A threadpool worker thread entered a callback, which left with background priorities set.
3156 /// This is unexpected, indicating that the callback missed restoring the original priorities.2160 /// This is unexpected, indicating that the callback missed restoring the original priorities.
3157 CALLBACK_RETURNED_PRI_BACK = 0xC0000720,2161 CALLBACK_RETURNED_PRI_BACK = 0xC0000720,
3158
3159 /// The attempted operation required self healing to be enabled.2162 /// The attempted operation required self healing to be enabled.
3160 DISK_REPAIR_DISABLED = 0xC0000800,2163 DISK_REPAIR_DISABLED = 0xC0000800,
3161
3162 /// The directory service cannot perform the requested operation because a domain rename operation is in progress.2164 /// The directory service cannot perform the requested operation because a domain rename operation is in progress.
3163 DS_DOMAIN_RENAME_IN_PROGRESS = 0xC0000801,2165 DS_DOMAIN_RENAME_IN_PROGRESS = 0xC0000801,
3164
3165 /// An operation failed because the storage quota was exceeded.2166 /// An operation failed because the storage quota was exceeded.
3166 DISK_QUOTA_EXCEEDED = 0xC0000802,2167 DISK_QUOTA_EXCEEDED = 0xC0000802,
3167
3168 /// An operation failed because the content was blocked.2168 /// An operation failed because the content was blocked.
3169 CONTENT_BLOCKED = 0xC0000804,2169 CONTENT_BLOCKED = 0xC0000804,
3170
3171 /// The operation could not be completed due to bad clusters on disk.2170 /// The operation could not be completed due to bad clusters on disk.
3172 BAD_CLUSTERS = 0xC0000805,2171 BAD_CLUSTERS = 0xC0000805,
3173
3174 /// The operation could not be completed because the volume is dirty. Please run the Chkdsk utility and try again.2172 /// The operation could not be completed because the volume is dirty. Please run the Chkdsk utility and try again.
3175 VOLUME_DIRTY = 0xC0000806,2173 VOLUME_DIRTY = 0xC0000806,
3176
3177 /// This file is checked out or locked for editing by another user.2174 /// This file is checked out or locked for editing by another user.
3178 FILE_CHECKED_OUT = 0xC0000901,2175 FILE_CHECKED_OUT = 0xC0000901,
3179
3180 /// The file must be checked out before saving changes.2176 /// The file must be checked out before saving changes.
3181 CHECKOUT_REQUIRED = 0xC0000902,2177 CHECKOUT_REQUIRED = 0xC0000902,
3182
3183 /// The file type being saved or retrieved has been blocked.2178 /// The file type being saved or retrieved has been blocked.
3184 BAD_FILE_TYPE = 0xC0000903,2179 BAD_FILE_TYPE = 0xC0000903,
3185
3186 /// The file size exceeds the limit allowed and cannot be saved.2180 /// The file size exceeds the limit allowed and cannot be saved.
3187 FILE_TOO_LARGE = 0xC0000904,2181 FILE_TOO_LARGE = 0xC0000904,
3188
3189 /// Access Denied. Before opening files in this location, you must first browse to the e.g.2182 /// Access Denied. Before opening files in this location, you must first browse to the e.g.
3190 /// site and select the option to log on automatically.2183 /// site and select the option to log on automatically.
3191 FORMS_AUTH_REQUIRED = 0xC0000905,2184 FORMS_AUTH_REQUIRED = 0xC0000905,
3192
3193 /// The operation did not complete successfully because the file contains a virus.2185 /// The operation did not complete successfully because the file contains a virus.
3194 VIRUS_INFECTED = 0xC0000906,2186 VIRUS_INFECTED = 0xC0000906,
3195
3196 /// This file contains a virus and cannot be opened.2187 /// This file contains a virus and cannot be opened.
3197 /// Due to the nature of this virus, the file has been removed from this location.2188 /// Due to the nature of this virus, the file has been removed from this location.
3198 VIRUS_DELETED = 0xC0000907,2189 VIRUS_DELETED = 0xC0000907,
3199
3200 /// The resources required for this device conflict with the MCFG table.2190 /// The resources required for this device conflict with the MCFG table.
3201 BAD_MCFG_TABLE = 0xC0000908,2191 BAD_MCFG_TABLE = 0xC0000908,
3202
3203 /// The operation did not complete successfully because it would cause an oplock to be broken.2192 /// The operation did not complete successfully because it would cause an oplock to be broken.
3204 /// The caller has requested that existing oplocks not be broken.2193 /// The caller has requested that existing oplocks not be broken.
3205 CANNOT_BREAK_OPLOCK = 0xC0000909,2194 CANNOT_BREAK_OPLOCK = 0xC0000909,
3206
3207 /// WOW Assertion Error.2195 /// WOW Assertion Error.
3208 WOW_ASSERTION = 0xC0009898,2196 WOW_ASSERTION = 0xC0009898,
3209
3210 /// The cryptographic signature is invalid.2197 /// The cryptographic signature is invalid.
3211 INVALID_SIGNATURE = 0xC000A000,2198 INVALID_SIGNATURE = 0xC000A000,
3212
3213 /// The cryptographic provider does not support HMAC.2199 /// The cryptographic provider does not support HMAC.
3214 HMAC_NOT_SUPPORTED = 0xC000A001,2200 HMAC_NOT_SUPPORTED = 0xC000A001,
3215
3216 /// The IPsec queue overflowed.2201 /// The IPsec queue overflowed.
3217 IPSEC_QUEUE_OVERFLOW = 0xC000A010,2202 IPSEC_QUEUE_OVERFLOW = 0xC000A010,
3218
3219 /// The neighbor discovery queue overflowed.2203 /// The neighbor discovery queue overflowed.
3220 ND_QUEUE_OVERFLOW = 0xC000A011,2204 ND_QUEUE_OVERFLOW = 0xC000A011,
3221
3222 /// An Internet Control Message Protocol (ICMP) hop limit exceeded error was received.2205 /// An Internet Control Message Protocol (ICMP) hop limit exceeded error was received.
3223 HOPLIMIT_EXCEEDED = 0xC000A012,2206 HOPLIMIT_EXCEEDED = 0xC000A012,
3224
3225 /// The protocol is not installed on the local machine.2207 /// The protocol is not installed on the local machine.
3226 PROTOCOL_NOT_SUPPORTED = 0xC000A013,2208 PROTOCOL_NOT_SUPPORTED = 0xC000A013,
3227
3228 /// {Delayed Write Failed} Windows was unable to save all the data for the file %hs; the data has been lost.2209 /// {Delayed Write Failed} Windows was unable to save all the data for the file %hs; the data has been lost.
3229 /// This error might be caused by network connectivity issues. Try to save this file elsewhere.2210 /// This error might be caused by network connectivity issues. Try to save this file elsewhere.
3230 LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED = 0xC000A080,2211 LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED = 0xC000A080,
3231
3232 /// {Delayed Write Failed} Windows was unable to save all the data for the file %hs; the data has been lost.2212 /// {Delayed Write Failed} Windows was unable to save all the data for the file %hs; the data has been lost.
3233 /// This error was returned by the server on which the file exists. Try to save this file elsewhere.2213 /// This error was returned by the server on which the file exists. Try to save this file elsewhere.
3234 LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR = 0xC000A081,2214 LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR = 0xC000A081,
3235
3236 /// {Delayed Write Failed} Windows was unable to save all the data for the file %hs; the data has been lost.2215 /// {Delayed Write Failed} Windows was unable to save all the data for the file %hs; the data has been lost.
3237 /// This error might be caused if the device has been removed or the media is write-protected.2216 /// This error might be caused if the device has been removed or the media is write-protected.
3238 LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR = 0xC000A082,2217 LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR = 0xC000A082,
3239
3240 /// Windows was unable to parse the requested XML data.2218 /// Windows was unable to parse the requested XML data.
3241 XML_PARSE_ERROR = 0xC000A083,2219 XML_PARSE_ERROR = 0xC000A083,
3242
3243 /// An error was encountered while processing an XML digital signature.2220 /// An error was encountered while processing an XML digital signature.
3244 XMLDSIG_ERROR = 0xC000A084,2221 XMLDSIG_ERROR = 0xC000A084,
3245
3246 /// This indicates that the caller made the connection request in the wrong routing compartment.2222 /// This indicates that the caller made the connection request in the wrong routing compartment.
3247 WRONG_COMPARTMENT = 0xC000A085,2223 WRONG_COMPARTMENT = 0xC000A085,
3248
3249 /// This indicates that there was an AuthIP failure when attempting to connect to the remote host.2224 /// This indicates that there was an AuthIP failure when attempting to connect to the remote host.
3250 AUTHIP_FAILURE = 0xC000A086,2225 AUTHIP_FAILURE = 0xC000A086,
3251
3252 /// OID mapped groups cannot have members.2226 /// OID mapped groups cannot have members.
3253 DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS = 0xC000A087,2227 DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS = 0xC000A087,
3254
3255 /// The specified OID cannot be found.2228 /// The specified OID cannot be found.
3256 DS_OID_NOT_FOUND = 0xC000A088,2229 DS_OID_NOT_FOUND = 0xC000A088,
3257
3258 /// Hash generation for the specified version and hash type is not enabled on server.2230 /// Hash generation for the specified version and hash type is not enabled on server.
3259 HASH_NOT_SUPPORTED = 0xC000A100,2231 HASH_NOT_SUPPORTED = 0xC000A100,
3260
3261 /// The hash requests is not present or not up to date with the current file contents.2232 /// The hash requests is not present or not up to date with the current file contents.
3262 HASH_NOT_PRESENT = 0xC000A101,2233 HASH_NOT_PRESENT = 0xC000A101,
3263
3264 /// A file system filter on the server has not opted in for Offload Read support.2234 /// A file system filter on the server has not opted in for Offload Read support.
3265 OFFLOAD_READ_FLT_NOT_SUPPORTED = 0xC000A2A1,2235 OFFLOAD_READ_FLT_NOT_SUPPORTED = 0xC000A2A1,
3266
3267 /// A file system filter on the server has not opted in for Offload Write support.2236 /// A file system filter on the server has not opted in for Offload Write support.
3268 OFFLOAD_WRITE_FLT_NOT_SUPPORTED = 0xC000A2A2,2237 OFFLOAD_WRITE_FLT_NOT_SUPPORTED = 0xC000A2A2,
3269
3270 /// Offload read operations cannot be performed on:2238 /// Offload read operations cannot be performed on:
3271 /// - Compressed files2239 /// - Compressed files
3272 /// - Sparse files2240 /// - Sparse files
3273 /// - Encrypted files2241 /// - Encrypted files
3274 /// - File system metadata files2242 /// - File system metadata files
3275 OFFLOAD_READ_FILE_NOT_SUPPORTED = 0xC000A2A3,2243 OFFLOAD_READ_FILE_NOT_SUPPORTED = 0xC000A2A3,
3276
3277 /// Offload write operations cannot be performed on:2244 /// Offload write operations cannot be performed on:
3278 /// - Compressed files2245 /// - Compressed files
3279 /// - Sparse files2246 /// - Sparse files
3280 /// - Encrypted files2247 /// - Encrypted files
3281 /// - File system metadata files2248 /// - File system metadata files
3282 OFFLOAD_WRITE_FILE_NOT_SUPPORTED = 0xC000A2A4,2249 OFFLOAD_WRITE_FILE_NOT_SUPPORTED = 0xC000A2A4,
3283
3284 /// The debugger did not perform a state change.2250 /// The debugger did not perform a state change.
3285 DBG_NO_STATE_CHANGE = 0xC0010001,2251 DBG_NO_STATE_CHANGE = 0xC0010001,
3286
3287 /// The debugger found that the application is not idle.2252 /// The debugger found that the application is not idle.
3288 DBG_APP_NOT_IDLE = 0xC0010002,2253 DBG_APP_NOT_IDLE = 0xC0010002,
3289
3290 /// The string binding is invalid.2254 /// The string binding is invalid.
3291 RPC_NT_INVALID_STRING_BINDING = 0xC0020001,2255 RPC_NT_INVALID_STRING_BINDING = 0xC0020001,
3292
3293 /// The binding handle is not the correct type.2256 /// The binding handle is not the correct type.
3294 RPC_NT_WRONG_KIND_OF_BINDING = 0xC0020002,2257 RPC_NT_WRONG_KIND_OF_BINDING = 0xC0020002,
3295
3296 /// The binding handle is invalid.2258 /// The binding handle is invalid.
3297 RPC_NT_INVALID_BINDING = 0xC0020003,2259 RPC_NT_INVALID_BINDING = 0xC0020003,
3298
3299 /// The RPC protocol sequence is not supported.2260 /// The RPC protocol sequence is not supported.
3300 RPC_NT_PROTSEQ_NOT_SUPPORTED = 0xC0020004,2261 RPC_NT_PROTSEQ_NOT_SUPPORTED = 0xC0020004,
3301
3302 /// The RPC protocol sequence is invalid.2262 /// The RPC protocol sequence is invalid.
3303 RPC_NT_INVALID_RPC_PROTSEQ = 0xC0020005,2263 RPC_NT_INVALID_RPC_PROTSEQ = 0xC0020005,
3304
3305 /// The string UUID is invalid.2264 /// The string UUID is invalid.
3306 RPC_NT_INVALID_STRING_UUID = 0xC0020006,2265 RPC_NT_INVALID_STRING_UUID = 0xC0020006,
3307
3308 /// The endpoint format is invalid.2266 /// The endpoint format is invalid.
3309 RPC_NT_INVALID_ENDPOINT_FORMAT = 0xC0020007,2267 RPC_NT_INVALID_ENDPOINT_FORMAT = 0xC0020007,
3310
3311 /// The network address is invalid.2268 /// The network address is invalid.
3312 RPC_NT_INVALID_NET_ADDR = 0xC0020008,2269 RPC_NT_INVALID_NET_ADDR = 0xC0020008,
3313
3314 /// No endpoint was found.2270 /// No endpoint was found.
3315 RPC_NT_NO_ENDPOINT_FOUND = 0xC0020009,2271 RPC_NT_NO_ENDPOINT_FOUND = 0xC0020009,
3316
3317 /// The time-out value is invalid.2272 /// The time-out value is invalid.
3318 RPC_NT_INVALID_TIMEOUT = 0xC002000A,2273 RPC_NT_INVALID_TIMEOUT = 0xC002000A,
3319
3320 /// The object UUID was not found.2274 /// The object UUID was not found.
3321 RPC_NT_OBJECT_NOT_FOUND = 0xC002000B,2275 RPC_NT_OBJECT_NOT_FOUND = 0xC002000B,
3322
3323 /// The object UUID has already been registered.2276 /// The object UUID has already been registered.
3324 RPC_NT_ALREADY_REGISTERED = 0xC002000C,2277 RPC_NT_ALREADY_REGISTERED = 0xC002000C,
3325
3326 /// The type UUID has already been registered.2278 /// The type UUID has already been registered.
3327 RPC_NT_TYPE_ALREADY_REGISTERED = 0xC002000D,2279 RPC_NT_TYPE_ALREADY_REGISTERED = 0xC002000D,
3328
3329 /// The RPC server is already listening.2280 /// The RPC server is already listening.
3330 RPC_NT_ALREADY_LISTENING = 0xC002000E,2281 RPC_NT_ALREADY_LISTENING = 0xC002000E,
3331
3332 /// No protocol sequences have been registered.2282 /// No protocol sequences have been registered.
3333 RPC_NT_NO_PROTSEQS_REGISTERED = 0xC002000F,2283 RPC_NT_NO_PROTSEQS_REGISTERED = 0xC002000F,
3334
3335 /// The RPC server is not listening.2284 /// The RPC server is not listening.
3336 RPC_NT_NOT_LISTENING = 0xC0020010,2285 RPC_NT_NOT_LISTENING = 0xC0020010,
3337
3338 /// The manager type is unknown.2286 /// The manager type is unknown.
3339 RPC_NT_UNKNOWN_MGR_TYPE = 0xC0020011,2287 RPC_NT_UNKNOWN_MGR_TYPE = 0xC0020011,
3340
3341 /// The interface is unknown.2288 /// The interface is unknown.
3342 RPC_NT_UNKNOWN_IF = 0xC0020012,2289 RPC_NT_UNKNOWN_IF = 0xC0020012,
3343
3344 /// There are no bindings.2290 /// There are no bindings.
3345 RPC_NT_NO_BINDINGS = 0xC0020013,2291 RPC_NT_NO_BINDINGS = 0xC0020013,
3346
3347 /// There are no protocol sequences.2292 /// There are no protocol sequences.
3348 RPC_NT_NO_PROTSEQS = 0xC0020014,2293 RPC_NT_NO_PROTSEQS = 0xC0020014,
3349
3350 /// The endpoint cannot be created.2294 /// The endpoint cannot be created.
3351 RPC_NT_CANT_CREATE_ENDPOINT = 0xC0020015,2295 RPC_NT_CANT_CREATE_ENDPOINT = 0xC0020015,
3352
3353 /// Insufficient resources are available to complete this operation.2296 /// Insufficient resources are available to complete this operation.
3354 RPC_NT_OUT_OF_RESOURCES = 0xC0020016,2297 RPC_NT_OUT_OF_RESOURCES = 0xC0020016,
3355
3356 /// The RPC server is unavailable.2298 /// The RPC server is unavailable.
3357 RPC_NT_SERVER_UNAVAILABLE = 0xC0020017,2299 RPC_NT_SERVER_UNAVAILABLE = 0xC0020017,
3358
3359 /// The RPC server is too busy to complete this operation.2300 /// The RPC server is too busy to complete this operation.
3360 RPC_NT_SERVER_TOO_BUSY = 0xC0020018,2301 RPC_NT_SERVER_TOO_BUSY = 0xC0020018,
3361
3362 /// The network options are invalid.2302 /// The network options are invalid.
3363 RPC_NT_INVALID_NETWORK_OPTIONS = 0xC0020019,2303 RPC_NT_INVALID_NETWORK_OPTIONS = 0xC0020019,
3364
3365 /// No RPCs are active on this thread.2304 /// No RPCs are active on this thread.
3366 RPC_NT_NO_CALL_ACTIVE = 0xC002001A,2305 RPC_NT_NO_CALL_ACTIVE = 0xC002001A,
3367
3368 /// The RPC failed.2306 /// The RPC failed.
3369 RPC_NT_CALL_FAILED = 0xC002001B,2307 RPC_NT_CALL_FAILED = 0xC002001B,
3370
3371 /// The RPC failed and did not execute.2308 /// The RPC failed and did not execute.
3372 RPC_NT_CALL_FAILED_DNE = 0xC002001C,2309 RPC_NT_CALL_FAILED_DNE = 0xC002001C,
3373
3374 /// An RPC protocol error occurred.2310 /// An RPC protocol error occurred.
3375 RPC_NT_PROTOCOL_ERROR = 0xC002001D,2311 RPC_NT_PROTOCOL_ERROR = 0xC002001D,
3376
3377 /// The RPC server does not support the transfer syntax.2312 /// The RPC server does not support the transfer syntax.
3378 RPC_NT_UNSUPPORTED_TRANS_SYN = 0xC002001F,2313 RPC_NT_UNSUPPORTED_TRANS_SYN = 0xC002001F,
3379
3380 /// The type UUID is not supported.2314 /// The type UUID is not supported.
3381 RPC_NT_UNSUPPORTED_TYPE = 0xC0020021,2315 RPC_NT_UNSUPPORTED_TYPE = 0xC0020021,
3382
3383 /// The tag is invalid.2316 /// The tag is invalid.
3384 RPC_NT_INVALID_TAG = 0xC0020022,2317 RPC_NT_INVALID_TAG = 0xC0020022,
3385
3386 /// The array bounds are invalid.2318 /// The array bounds are invalid.
3387 RPC_NT_INVALID_BOUND = 0xC0020023,2319 RPC_NT_INVALID_BOUND = 0xC0020023,
3388
3389 /// The binding does not contain an entry name.2320 /// The binding does not contain an entry name.
3390 RPC_NT_NO_ENTRY_NAME = 0xC0020024,2321 RPC_NT_NO_ENTRY_NAME = 0xC0020024,
3391
3392 /// The name syntax is invalid.2322 /// The name syntax is invalid.
3393 RPC_NT_INVALID_NAME_SYNTAX = 0xC0020025,2323 RPC_NT_INVALID_NAME_SYNTAX = 0xC0020025,
3394
3395 /// The name syntax is not supported.2324 /// The name syntax is not supported.
3396 RPC_NT_UNSUPPORTED_NAME_SYNTAX = 0xC0020026,2325 RPC_NT_UNSUPPORTED_NAME_SYNTAX = 0xC0020026,
3397
3398 /// No network address is available to construct a UUID.2326 /// No network address is available to construct a UUID.
3399 RPC_NT_UUID_NO_ADDRESS = 0xC0020028,2327 RPC_NT_UUID_NO_ADDRESS = 0xC0020028,
3400
3401 /// The endpoint is a duplicate.2328 /// The endpoint is a duplicate.
3402 RPC_NT_DUPLICATE_ENDPOINT = 0xC0020029,2329 RPC_NT_DUPLICATE_ENDPOINT = 0xC0020029,
3403
3404 /// The authentication type is unknown.2330 /// The authentication type is unknown.
3405 RPC_NT_UNKNOWN_AUTHN_TYPE = 0xC002002A,2331 RPC_NT_UNKNOWN_AUTHN_TYPE = 0xC002002A,
3406
3407 /// The maximum number of calls is too small.2332 /// The maximum number of calls is too small.
3408 RPC_NT_MAX_CALLS_TOO_SMALL = 0xC002002B,2333 RPC_NT_MAX_CALLS_TOO_SMALL = 0xC002002B,
3409
3410 /// The string is too long.2334 /// The string is too long.
3411 RPC_NT_STRING_TOO_LONG = 0xC002002C,2335 RPC_NT_STRING_TOO_LONG = 0xC002002C,
3412
3413 /// The RPC protocol sequence was not found.2336 /// The RPC protocol sequence was not found.
3414 RPC_NT_PROTSEQ_NOT_FOUND = 0xC002002D,2337 RPC_NT_PROTSEQ_NOT_FOUND = 0xC002002D,
3415
3416 /// The procedure number is out of range.2338 /// The procedure number is out of range.
3417 RPC_NT_PROCNUM_OUT_OF_RANGE = 0xC002002E,2339 RPC_NT_PROCNUM_OUT_OF_RANGE = 0xC002002E,
3418
3419 /// The binding does not contain any authentication information.2340 /// The binding does not contain any authentication information.
3420 RPC_NT_BINDING_HAS_NO_AUTH = 0xC002002F,2341 RPC_NT_BINDING_HAS_NO_AUTH = 0xC002002F,
3421
3422 /// The authentication service is unknown.2342 /// The authentication service is unknown.
3423 RPC_NT_UNKNOWN_AUTHN_SERVICE = 0xC0020030,2343 RPC_NT_UNKNOWN_AUTHN_SERVICE = 0xC0020030,
3424
3425 /// The authentication level is unknown.2344 /// The authentication level is unknown.
3426 RPC_NT_UNKNOWN_AUTHN_LEVEL = 0xC0020031,2345 RPC_NT_UNKNOWN_AUTHN_LEVEL = 0xC0020031,
3427
3428 /// The security context is invalid.2346 /// The security context is invalid.
3429 RPC_NT_INVALID_AUTH_IDENTITY = 0xC0020032,2347 RPC_NT_INVALID_AUTH_IDENTITY = 0xC0020032,
3430
3431 /// The authorization service is unknown.2348 /// The authorization service is unknown.
3432 RPC_NT_UNKNOWN_AUTHZ_SERVICE = 0xC0020033,2349 RPC_NT_UNKNOWN_AUTHZ_SERVICE = 0xC0020033,
3433
3434 /// The entry is invalid.2350 /// The entry is invalid.
3435 EPT_NT_INVALID_ENTRY = 0xC0020034,2351 EPT_NT_INVALID_ENTRY = 0xC0020034,
3436
3437 /// The operation cannot be performed.2352 /// The operation cannot be performed.
3438 EPT_NT_CANT_PERFORM_OP = 0xC0020035,2353 EPT_NT_CANT_PERFORM_OP = 0xC0020035,
3439
3440 /// No more endpoints are available from the endpoint mapper.2354 /// No more endpoints are available from the endpoint mapper.
3441 EPT_NT_NOT_REGISTERED = 0xC0020036,2355 EPT_NT_NOT_REGISTERED = 0xC0020036,
3442
3443 /// No interfaces have been exported.2356 /// No interfaces have been exported.
3444 RPC_NT_NOTHING_TO_EXPORT = 0xC0020037,2357 RPC_NT_NOTHING_TO_EXPORT = 0xC0020037,
3445
3446 /// The entry name is incomplete.2358 /// The entry name is incomplete.
3447 RPC_NT_INCOMPLETE_NAME = 0xC0020038,2359 RPC_NT_INCOMPLETE_NAME = 0xC0020038,
3448
3449 /// The version option is invalid.2360 /// The version option is invalid.
3450 RPC_NT_INVALID_VERS_OPTION = 0xC0020039,2361 RPC_NT_INVALID_VERS_OPTION = 0xC0020039,
3451
3452 /// There are no more members.2362 /// There are no more members.
3453 RPC_NT_NO_MORE_MEMBERS = 0xC002003A,2363 RPC_NT_NO_MORE_MEMBERS = 0xC002003A,
3454
3455 /// There is nothing to unexport.2364 /// There is nothing to unexport.
3456 RPC_NT_NOT_ALL_OBJS_UNEXPORTED = 0xC002003B,2365 RPC_NT_NOT_ALL_OBJS_UNEXPORTED = 0xC002003B,
3457
3458 /// The interface was not found.2366 /// The interface was not found.
3459 RPC_NT_INTERFACE_NOT_FOUND = 0xC002003C,2367 RPC_NT_INTERFACE_NOT_FOUND = 0xC002003C,
3460
3461 /// The entry already exists.2368 /// The entry already exists.
3462 RPC_NT_ENTRY_ALREADY_EXISTS = 0xC002003D,2369 RPC_NT_ENTRY_ALREADY_EXISTS = 0xC002003D,
3463
3464 /// The entry was not found.2370 /// The entry was not found.
3465 RPC_NT_ENTRY_NOT_FOUND = 0xC002003E,2371 RPC_NT_ENTRY_NOT_FOUND = 0xC002003E,
3466
3467 /// The name service is unavailable.2372 /// The name service is unavailable.
3468 RPC_NT_NAME_SERVICE_UNAVAILABLE = 0xC002003F,2373 RPC_NT_NAME_SERVICE_UNAVAILABLE = 0xC002003F,
3469
3470 /// The network address family is invalid.2374 /// The network address family is invalid.
3471 RPC_NT_INVALID_NAF_ID = 0xC0020040,2375 RPC_NT_INVALID_NAF_ID = 0xC0020040,
3472
3473 /// The requested operation is not supported.2376 /// The requested operation is not supported.
3474 RPC_NT_CANNOT_SUPPORT = 0xC0020041,2377 RPC_NT_CANNOT_SUPPORT = 0xC0020041,
3475
3476 /// No security context is available to allow impersonation.2378 /// No security context is available to allow impersonation.
3477 RPC_NT_NO_CONTEXT_AVAILABLE = 0xC0020042,2379 RPC_NT_NO_CONTEXT_AVAILABLE = 0xC0020042,
3478
3479 /// An internal error occurred in the RPC.2380 /// An internal error occurred in the RPC.
3480 RPC_NT_INTERNAL_ERROR = 0xC0020043,2381 RPC_NT_INTERNAL_ERROR = 0xC0020043,
3481
3482 /// The RPC server attempted to divide an integer by zero.2382 /// The RPC server attempted to divide an integer by zero.
3483 RPC_NT_ZERO_DIVIDE = 0xC0020044,2383 RPC_NT_ZERO_DIVIDE = 0xC0020044,
3484
3485 /// An addressing error occurred in the RPC server.2384 /// An addressing error occurred in the RPC server.
3486 RPC_NT_ADDRESS_ERROR = 0xC0020045,2385 RPC_NT_ADDRESS_ERROR = 0xC0020045,
3487
3488 /// A floating point operation at the RPC server caused a divide by zero.2386 /// A floating point operation at the RPC server caused a divide by zero.
3489 RPC_NT_FP_DIV_ZERO = 0xC0020046,2387 RPC_NT_FP_DIV_ZERO = 0xC0020046,
3490
3491 /// A floating point underflow occurred at the RPC server.2388 /// A floating point underflow occurred at the RPC server.
3492 RPC_NT_FP_UNDERFLOW = 0xC0020047,2389 RPC_NT_FP_UNDERFLOW = 0xC0020047,
3493
3494 /// A floating point overflow occurred at the RPC server.2390 /// A floating point overflow occurred at the RPC server.
3495 RPC_NT_FP_OVERFLOW = 0xC0020048,2391 RPC_NT_FP_OVERFLOW = 0xC0020048,
3496
3497 /// An RPC is already in progress for this thread.2392 /// An RPC is already in progress for this thread.
3498 RPC_NT_CALL_IN_PROGRESS = 0xC0020049,2393 RPC_NT_CALL_IN_PROGRESS = 0xC0020049,
3499
3500 /// There are no more bindings.2394 /// There are no more bindings.
3501 RPC_NT_NO_MORE_BINDINGS = 0xC002004A,2395 RPC_NT_NO_MORE_BINDINGS = 0xC002004A,
3502
3503 /// The group member was not found.2396 /// The group member was not found.
3504 RPC_NT_GROUP_MEMBER_NOT_FOUND = 0xC002004B,2397 RPC_NT_GROUP_MEMBER_NOT_FOUND = 0xC002004B,
3505
3506 /// The endpoint mapper database entry could not be created.2398 /// The endpoint mapper database entry could not be created.
3507 EPT_NT_CANT_CREATE = 0xC002004C,2399 EPT_NT_CANT_CREATE = 0xC002004C,
3508
3509 /// The object UUID is the nil UUID.2400 /// The object UUID is the nil UUID.
3510 RPC_NT_INVALID_OBJECT = 0xC002004D,2401 RPC_NT_INVALID_OBJECT = 0xC002004D,
3511
3512 /// No interfaces have been registered.2402 /// No interfaces have been registered.
3513 RPC_NT_NO_INTERFACES = 0xC002004F,2403 RPC_NT_NO_INTERFACES = 0xC002004F,
3514
3515 /// The RPC was canceled.2404 /// The RPC was canceled.
3516 RPC_NT_CALL_CANCELLED = 0xC0020050,2405 RPC_NT_CALL_CANCELLED = 0xC0020050,
3517
3518 /// The binding handle does not contain all the required information.2406 /// The binding handle does not contain all the required information.
3519 RPC_NT_BINDING_INCOMPLETE = 0xC0020051,2407 RPC_NT_BINDING_INCOMPLETE = 0xC0020051,
3520
3521 /// A communications failure occurred during an RPC.2408 /// A communications failure occurred during an RPC.
3522 RPC_NT_COMM_FAILURE = 0xC0020052,2409 RPC_NT_COMM_FAILURE = 0xC0020052,
3523
3524 /// The requested authentication level is not supported.2410 /// The requested authentication level is not supported.
3525 RPC_NT_UNSUPPORTED_AUTHN_LEVEL = 0xC0020053,2411 RPC_NT_UNSUPPORTED_AUTHN_LEVEL = 0xC0020053,
3526
3527 /// No principal name was registered.2412 /// No principal name was registered.
3528 RPC_NT_NO_PRINC_NAME = 0xC0020054,2413 RPC_NT_NO_PRINC_NAME = 0xC0020054,
3529
3530 /// The error specified is not a valid Windows RPC error code.2414 /// The error specified is not a valid Windows RPC error code.
3531 RPC_NT_NOT_RPC_ERROR = 0xC0020055,2415 RPC_NT_NOT_RPC_ERROR = 0xC0020055,
3532
3533 /// A security package-specific error occurred.2416 /// A security package-specific error occurred.
3534 RPC_NT_SEC_PKG_ERROR = 0xC0020057,2417 RPC_NT_SEC_PKG_ERROR = 0xC0020057,
3535
3536 /// The thread was not canceled.2418 /// The thread was not canceled.
3537 RPC_NT_NOT_CANCELLED = 0xC0020058,2419 RPC_NT_NOT_CANCELLED = 0xC0020058,
3538
3539 /// Invalid asynchronous RPC handle.2420 /// Invalid asynchronous RPC handle.
3540 RPC_NT_INVALID_ASYNC_HANDLE = 0xC0020062,2421 RPC_NT_INVALID_ASYNC_HANDLE = 0xC0020062,
3541
3542 /// Invalid asynchronous RPC call handle for this operation.2422 /// Invalid asynchronous RPC call handle for this operation.
3543 RPC_NT_INVALID_ASYNC_CALL = 0xC0020063,2423 RPC_NT_INVALID_ASYNC_CALL = 0xC0020063,
3544
3545 /// Access to the HTTP proxy is denied.2424 /// Access to the HTTP proxy is denied.
3546 RPC_NT_PROXY_ACCESS_DENIED = 0xC0020064,2425 RPC_NT_PROXY_ACCESS_DENIED = 0xC0020064,
3547
3548 /// The list of RPC servers available for auto-handle binding has been exhausted.2426 /// The list of RPC servers available for auto-handle binding has been exhausted.
3549 RPC_NT_NO_MORE_ENTRIES = 0xC0030001,2427 RPC_NT_NO_MORE_ENTRIES = 0xC0030001,
3550
3551 /// The file designated by DCERPCCHARTRANS cannot be opened.2428 /// The file designated by DCERPCCHARTRANS cannot be opened.
3552 RPC_NT_SS_CHAR_TRANS_OPEN_FAIL = 0xC0030002,2429 RPC_NT_SS_CHAR_TRANS_OPEN_FAIL = 0xC0030002,
3553
3554 /// The file containing the character translation table has fewer than 512 bytes.2430 /// The file containing the character translation table has fewer than 512 bytes.
3555 RPC_NT_SS_CHAR_TRANS_SHORT_FILE = 0xC0030003,2431 RPC_NT_SS_CHAR_TRANS_SHORT_FILE = 0xC0030003,
3556
3557 /// A null context handle is passed as an [in] parameter.2432 /// A null context handle is passed as an [in] parameter.
3558 RPC_NT_SS_IN_NULL_CONTEXT = 0xC0030004,2433 RPC_NT_SS_IN_NULL_CONTEXT = 0xC0030004,
3559
3560 /// The context handle does not match any known context handles.2434 /// The context handle does not match any known context handles.
3561 RPC_NT_SS_CONTEXT_MISMATCH = 0xC0030005,2435 RPC_NT_SS_CONTEXT_MISMATCH = 0xC0030005,
3562
3563 /// The context handle changed during a call.2436 /// The context handle changed during a call.
3564 RPC_NT_SS_CONTEXT_DAMAGED = 0xC0030006,2437 RPC_NT_SS_CONTEXT_DAMAGED = 0xC0030006,
3565
3566 /// The binding handles passed to an RPC do not match.2438 /// The binding handles passed to an RPC do not match.
3567 RPC_NT_SS_HANDLES_MISMATCH = 0xC0030007,2439 RPC_NT_SS_HANDLES_MISMATCH = 0xC0030007,
3568
3569 /// The stub is unable to get the call handle.2440 /// The stub is unable to get the call handle.
3570 RPC_NT_SS_CANNOT_GET_CALL_HANDLE = 0xC0030008,2441 RPC_NT_SS_CANNOT_GET_CALL_HANDLE = 0xC0030008,
3571
3572 /// A null reference pointer was passed to the stub.2442 /// A null reference pointer was passed to the stub.
3573 RPC_NT_NULL_REF_POINTER = 0xC0030009,2443 RPC_NT_NULL_REF_POINTER = 0xC0030009,
3574
3575 /// The enumeration value is out of range.2444 /// The enumeration value is out of range.
3576 RPC_NT_ENUM_VALUE_OUT_OF_RANGE = 0xC003000A,2445 RPC_NT_ENUM_VALUE_OUT_OF_RANGE = 0xC003000A,
3577
3578 /// The byte count is too small.2446 /// The byte count is too small.
3579 RPC_NT_BYTE_COUNT_TOO_SMALL = 0xC003000B,2447 RPC_NT_BYTE_COUNT_TOO_SMALL = 0xC003000B,
3580
3581 /// The stub received bad data.2448 /// The stub received bad data.
3582 RPC_NT_BAD_STUB_DATA = 0xC003000C,2449 RPC_NT_BAD_STUB_DATA = 0xC003000C,
3583
3584 /// Invalid operation on the encoding/decoding handle.2450 /// Invalid operation on the encoding/decoding handle.
3585 RPC_NT_INVALID_ES_ACTION = 0xC0030059,2451 RPC_NT_INVALID_ES_ACTION = 0xC0030059,
3586
3587 /// Incompatible version of the serializing package.2452 /// Incompatible version of the serializing package.
3588 RPC_NT_WRONG_ES_VERSION = 0xC003005A,2453 RPC_NT_WRONG_ES_VERSION = 0xC003005A,
3589
3590 /// Incompatible version of the RPC stub.2454 /// Incompatible version of the RPC stub.
3591 RPC_NT_WRONG_STUB_VERSION = 0xC003005B,2455 RPC_NT_WRONG_STUB_VERSION = 0xC003005B,
3592
3593 /// The RPC pipe object is invalid or corrupt.2456 /// The RPC pipe object is invalid or corrupt.
3594 RPC_NT_INVALID_PIPE_OBJECT = 0xC003005C,2457 RPC_NT_INVALID_PIPE_OBJECT = 0xC003005C,
3595
3596 /// An invalid operation was attempted on an RPC pipe object.2458 /// An invalid operation was attempted on an RPC pipe object.
3597 RPC_NT_INVALID_PIPE_OPERATION = 0xC003005D,2459 RPC_NT_INVALID_PIPE_OPERATION = 0xC003005D,
3598
3599 /// Unsupported RPC pipe version.2460 /// Unsupported RPC pipe version.
3600 RPC_NT_WRONG_PIPE_VERSION = 0xC003005E,2461 RPC_NT_WRONG_PIPE_VERSION = 0xC003005E,
3601
3602 /// The RPC pipe object has already been closed.2462 /// The RPC pipe object has already been closed.
3603 RPC_NT_PIPE_CLOSED = 0xC003005F,2463 RPC_NT_PIPE_CLOSED = 0xC003005F,
3604
3605 /// The RPC call completed before all pipes were processed.2464 /// The RPC call completed before all pipes were processed.
3606 RPC_NT_PIPE_DISCIPLINE_ERROR = 0xC0030060,2465 RPC_NT_PIPE_DISCIPLINE_ERROR = 0xC0030060,
3607
3608 /// No more data is available from the RPC pipe.2466 /// No more data is available from the RPC pipe.
3609 RPC_NT_PIPE_EMPTY = 0xC0030061,2467 RPC_NT_PIPE_EMPTY = 0xC0030061,
3610
3611 /// A device is missing in the system BIOS MPS table. This device will not be used.2468 /// A device is missing in the system BIOS MPS table. This device will not be used.
3612 /// Contact your system vendor for a system BIOS update.2469 /// Contact your system vendor for a system BIOS update.
3613 PNP_BAD_MPS_TABLE = 0xC0040035,2470 PNP_BAD_MPS_TABLE = 0xC0040035,
3614
3615 /// A translator failed to translate resources.2471 /// A translator failed to translate resources.
3616 PNP_TRANSLATION_FAILED = 0xC0040036,2472 PNP_TRANSLATION_FAILED = 0xC0040036,
3617
3618 /// An IRQ translator failed to translate resources.2473 /// An IRQ translator failed to translate resources.
3619 PNP_IRQ_TRANSLATION_FAILED = 0xC0040037,2474 PNP_IRQ_TRANSLATION_FAILED = 0xC0040037,
3620
3621 /// Driver %2 returned an invalid ID for a child device (%3).2475 /// Driver %2 returned an invalid ID for a child device (%3).
3622 PNP_INVALID_ID = 0xC0040038,2476 PNP_INVALID_ID = 0xC0040038,
3623
3624 /// Reissue the given operation as a cached I/O operation2477 /// Reissue the given operation as a cached I/O operation
3625 IO_REISSUE_AS_CACHED = 0xC0040039,2478 IO_REISSUE_AS_CACHED = 0xC0040039,
3626
3627 /// Session name %1 is invalid.2479 /// Session name %1 is invalid.
3628 CTX_WINSTATION_NAME_INVALID = 0xC00A0001,2480 CTX_WINSTATION_NAME_INVALID = 0xC00A0001,
3629
3630 /// The protocol driver %1 is invalid.2481 /// The protocol driver %1 is invalid.
3631 CTX_INVALID_PD = 0xC00A0002,2482 CTX_INVALID_PD = 0xC00A0002,
3632
3633 /// The protocol driver %1 was not found in the system path.2483 /// The protocol driver %1 was not found in the system path.
3634 CTX_PD_NOT_FOUND = 0xC00A0003,2484 CTX_PD_NOT_FOUND = 0xC00A0003,
3635
3636 /// A close operation is pending on the terminal connection.2485 /// A close operation is pending on the terminal connection.
3637 CTX_CLOSE_PENDING = 0xC00A0006,2486 CTX_CLOSE_PENDING = 0xC00A0006,
3638
3639 /// No free output buffers are available.2487 /// No free output buffers are available.
3640 CTX_NO_OUTBUF = 0xC00A0007,2488 CTX_NO_OUTBUF = 0xC00A0007,
3641
3642 /// The MODEM.INF file was not found.2489 /// The MODEM.INF file was not found.
3643 CTX_MODEM_INF_NOT_FOUND = 0xC00A0008,2490 CTX_MODEM_INF_NOT_FOUND = 0xC00A0008,
3644
3645 /// The modem (%1) was not found in the MODEM.INF file.2491 /// The modem (%1) was not found in the MODEM.INF file.
3646 CTX_INVALID_MODEMNAME = 0xC00A0009,2492 CTX_INVALID_MODEMNAME = 0xC00A0009,
3647
3648 /// The modem did not accept the command sent to it.2493 /// The modem did not accept the command sent to it.
3649 /// Verify that the configured modem name matches the attached modem.2494 /// Verify that the configured modem name matches the attached modem.
3650 CTX_RESPONSE_ERROR = 0xC00A000A,2495 CTX_RESPONSE_ERROR = 0xC00A000A,
3651
3652 /// The modem did not respond to the command sent to it.2496 /// The modem did not respond to the command sent to it.
3653 /// Verify that the modem cable is properly attached and the modem is turned on.2497 /// Verify that the modem cable is properly attached and the modem is turned on.
3654 CTX_MODEM_RESPONSE_TIMEOUT = 0xC00A000B,2498 CTX_MODEM_RESPONSE_TIMEOUT = 0xC00A000B,
3655
3656 /// Carrier detection has failed or the carrier has been dropped due to disconnection.2499 /// Carrier detection has failed or the carrier has been dropped due to disconnection.
3657 CTX_MODEM_RESPONSE_NO_CARRIER = 0xC00A000C,2500 CTX_MODEM_RESPONSE_NO_CARRIER = 0xC00A000C,
3658
3659 /// A dial tone was not detected within the required time.2501 /// A dial tone was not detected within the required time.
3660 /// Verify that the phone cable is properly attached and functional.2502 /// Verify that the phone cable is properly attached and functional.
3661 CTX_MODEM_RESPONSE_NO_DIALTONE = 0xC00A000D,2503 CTX_MODEM_RESPONSE_NO_DIALTONE = 0xC00A000D,
3662
3663 /// A busy signal was detected at a remote site on callback.2504 /// A busy signal was detected at a remote site on callback.
3664 CTX_MODEM_RESPONSE_BUSY = 0xC00A000E,2505 CTX_MODEM_RESPONSE_BUSY = 0xC00A000E,
3665
3666 /// A voice was detected at a remote site on callback.2506 /// A voice was detected at a remote site on callback.
3667 CTX_MODEM_RESPONSE_VOICE = 0xC00A000F,2507 CTX_MODEM_RESPONSE_VOICE = 0xC00A000F,
3668
3669 /// Transport driver error.2508 /// Transport driver error.
3670 CTX_TD_ERROR = 0xC00A0010,2509 CTX_TD_ERROR = 0xC00A0010,
3671
3672 /// The client you are using is not licensed to use this system. Your logon request is denied.2510 /// The client you are using is not licensed to use this system. Your logon request is denied.
3673 CTX_LICENSE_CLIENT_INVALID = 0xC00A0012,2511 CTX_LICENSE_CLIENT_INVALID = 0xC00A0012,
3674
3675 /// The system has reached its licensed logon limit. Try again later.2512 /// The system has reached its licensed logon limit. Try again later.
3676 CTX_LICENSE_NOT_AVAILABLE = 0xC00A0013,2513 CTX_LICENSE_NOT_AVAILABLE = 0xC00A0013,
3677
3678 /// The system license has expired. Your logon request is denied.2514 /// The system license has expired. Your logon request is denied.
3679 CTX_LICENSE_EXPIRED = 0xC00A0014,2515 CTX_LICENSE_EXPIRED = 0xC00A0014,
3680
3681 /// The specified session cannot be found.2516 /// The specified session cannot be found.
3682 CTX_WINSTATION_NOT_FOUND = 0xC00A0015,2517 CTX_WINSTATION_NOT_FOUND = 0xC00A0015,
3683
3684 /// The specified session name is already in use.2518 /// The specified session name is already in use.
3685 CTX_WINSTATION_NAME_COLLISION = 0xC00A0016,2519 CTX_WINSTATION_NAME_COLLISION = 0xC00A0016,
3686
3687 /// The requested operation cannot be completed because the terminal connection is currently processing a connect, disconnect, reset, or delete operation.2520 /// The requested operation cannot be completed because the terminal connection is currently processing a connect, disconnect, reset, or delete operation.
3688 CTX_WINSTATION_BUSY = 0xC00A0017,2521 CTX_WINSTATION_BUSY = 0xC00A0017,
3689
3690 /// An attempt has been made to connect to a session whose video mode is not supported by the current client.2522 /// An attempt has been made to connect to a session whose video mode is not supported by the current client.
3691 CTX_BAD_VIDEO_MODE = 0xC00A0018,2523 CTX_BAD_VIDEO_MODE = 0xC00A0018,
3692
3693 /// The application attempted to enable DOS graphics mode. DOS graphics mode is not supported.2524 /// The application attempted to enable DOS graphics mode. DOS graphics mode is not supported.
3694 CTX_GRAPHICS_INVALID = 0xC00A0022,2525 CTX_GRAPHICS_INVALID = 0xC00A0022,
3695
3696 /// The requested operation can be performed only on the system console.2526 /// The requested operation can be performed only on the system console.
3697 /// This is most often the result of a driver or system DLL requiring direct console access.2527 /// This is most often the result of a driver or system DLL requiring direct console access.
3698 CTX_NOT_CONSOLE = 0xC00A0024,2528 CTX_NOT_CONSOLE = 0xC00A0024,
3699
3700 /// The client failed to respond to the server connect message.2529 /// The client failed to respond to the server connect message.
3701 CTX_CLIENT_QUERY_TIMEOUT = 0xC00A0026,2530 CTX_CLIENT_QUERY_TIMEOUT = 0xC00A0026,
3702
3703 /// Disconnecting the console session is not supported.2531 /// Disconnecting the console session is not supported.
3704 CTX_CONSOLE_DISCONNECT = 0xC00A0027,2532 CTX_CONSOLE_DISCONNECT = 0xC00A0027,
3705
3706 /// Reconnecting a disconnected session to the console is not supported.2533 /// Reconnecting a disconnected session to the console is not supported.
3707 CTX_CONSOLE_CONNECT = 0xC00A0028,2534 CTX_CONSOLE_CONNECT = 0xC00A0028,
3708
3709 /// The request to control another session remotely was denied.2535 /// The request to control another session remotely was denied.
3710 CTX_SHADOW_DENIED = 0xC00A002A,2536 CTX_SHADOW_DENIED = 0xC00A002A,
3711
3712 /// A process has requested access to a session, but has not been granted those access rights.2537 /// A process has requested access to a session, but has not been granted those access rights.
3713 CTX_WINSTATION_ACCESS_DENIED = 0xC00A002B,2538 CTX_WINSTATION_ACCESS_DENIED = 0xC00A002B,
3714
3715 /// The terminal connection driver %1 is invalid.2539 /// The terminal connection driver %1 is invalid.
3716 CTX_INVALID_WD = 0xC00A002E,2540 CTX_INVALID_WD = 0xC00A002E,
3717
3718 /// The terminal connection driver %1 was not found in the system path.2541 /// The terminal connection driver %1 was not found in the system path.
3719 CTX_WD_NOT_FOUND = 0xC00A002F,2542 CTX_WD_NOT_FOUND = 0xC00A002F,
3720
3721 /// The requested session cannot be controlled remotely.2543 /// The requested session cannot be controlled remotely.
3722 /// You cannot control your own session, a session that is trying to control your session, a session that has no user logged on, or other sessions from the console.2544 /// You cannot control your own session, a session that is trying to control your session, a session that has no user logged on, or other sessions from the console.
3723 CTX_SHADOW_INVALID = 0xC00A0030,2545 CTX_SHADOW_INVALID = 0xC00A0030,
3724
3725 /// The requested session is not configured to allow remote control.2546 /// The requested session is not configured to allow remote control.
3726 CTX_SHADOW_DISABLED = 0xC00A0031,2547 CTX_SHADOW_DISABLED = 0xC00A0031,
3727
3728 /// The RDP protocol component %2 detected an error in the protocol stream and has disconnected the client.2548 /// The RDP protocol component %2 detected an error in the protocol stream and has disconnected the client.
3729 RDP_PROTOCOL_ERROR = 0xC00A0032,2549 RDP_PROTOCOL_ERROR = 0xC00A0032,
3730
3731 /// Your request to connect to this terminal server has been rejected.2550 /// Your request to connect to this terminal server has been rejected.
3732 /// Your terminal server client license number has not been entered for this copy of the terminal client.2551 /// Your terminal server client license number has not been entered for this copy of the terminal client.
3733 /// Contact your system administrator for help in entering a valid, unique license number for this terminal server client. Click OK to continue.2552 /// Contact your system administrator for help in entering a valid, unique license number for this terminal server client. Click OK to continue.
3734 CTX_CLIENT_LICENSE_NOT_SET = 0xC00A0033,2553 CTX_CLIENT_LICENSE_NOT_SET = 0xC00A0033,
3735
3736 /// Your request to connect to this terminal server has been rejected.2554 /// Your request to connect to this terminal server has been rejected.
3737 /// Your terminal server client license number is currently being used by another user.2555 /// Your terminal server client license number is currently being used by another user.
3738 /// Contact your system administrator to obtain a new copy of the terminal server client with a valid, unique license number. Click OK to continue.2556 /// Contact your system administrator to obtain a new copy of the terminal server client with a valid, unique license number. Click OK to continue.
3739 CTX_CLIENT_LICENSE_IN_USE = 0xC00A0034,2557 CTX_CLIENT_LICENSE_IN_USE = 0xC00A0034,
3740
3741 /// The remote control of the console was terminated because the display mode was changed.2558 /// The remote control of the console was terminated because the display mode was changed.
3742 /// Changing the display mode in a remote control session is not supported.2559 /// Changing the display mode in a remote control session is not supported.
3743 CTX_SHADOW_ENDED_BY_MODE_CHANGE = 0xC00A0035,2560 CTX_SHADOW_ENDED_BY_MODE_CHANGE = 0xC00A0035,
3744
3745 /// Remote control could not be terminated because the specified session is not currently being remotely controlled.2561 /// Remote control could not be terminated because the specified session is not currently being remotely controlled.
3746 CTX_SHADOW_NOT_RUNNING = 0xC00A0036,2562 CTX_SHADOW_NOT_RUNNING = 0xC00A0036,
3747
3748 /// Your interactive logon privilege has been disabled. Contact your system administrator.2563 /// Your interactive logon privilege has been disabled. Contact your system administrator.
3749 CTX_LOGON_DISABLED = 0xC00A0037,2564 CTX_LOGON_DISABLED = 0xC00A0037,
3750
3751 /// The terminal server security layer detected an error in the protocol stream and has disconnected the client.2565 /// The terminal server security layer detected an error in the protocol stream and has disconnected the client.
3752 CTX_SECURITY_LAYER_ERROR = 0xC00A0038,2566 CTX_SECURITY_LAYER_ERROR = 0xC00A0038,
3753
3754 /// The target session is incompatible with the current session.2567 /// The target session is incompatible with the current session.
3755 TS_INCOMPATIBLE_SESSIONS = 0xC00A0039,2568 TS_INCOMPATIBLE_SESSIONS = 0xC00A0039,
3756
3757 /// The resource loader failed to find an MUI file.2569 /// The resource loader failed to find an MUI file.
3758 MUI_FILE_NOT_FOUND = 0xC00B0001,2570 MUI_FILE_NOT_FOUND = 0xC00B0001,
3759
3760 /// The resource loader failed to load an MUI file because the file failed to pass validation.2571 /// The resource loader failed to load an MUI file because the file failed to pass validation.
3761 MUI_INVALID_FILE = 0xC00B0002,2572 MUI_INVALID_FILE = 0xC00B0002,
3762
3763 /// The RC manifest is corrupted with garbage data, is an unsupported version, or is missing a required item.2573 /// The RC manifest is corrupted with garbage data, is an unsupported version, or is missing a required item.
3764 MUI_INVALID_RC_CONFIG = 0xC00B0003,2574 MUI_INVALID_RC_CONFIG = 0xC00B0003,
3765
3766 /// The RC manifest has an invalid culture name.2575 /// The RC manifest has an invalid culture name.
3767 MUI_INVALID_LOCALE_NAME = 0xC00B0004,2576 MUI_INVALID_LOCALE_NAME = 0xC00B0004,
3768
3769 /// The RC manifest has and invalid ultimate fallback name.2577 /// The RC manifest has and invalid ultimate fallback name.
3770 MUI_INVALID_ULTIMATEFALLBACK_NAME = 0xC00B0005,2578 MUI_INVALID_ULTIMATEFALLBACK_NAME = 0xC00B0005,
3771
3772 /// The resource loader cache does not have a loaded MUI entry.2579 /// The resource loader cache does not have a loaded MUI entry.
3773 MUI_FILE_NOT_LOADED = 0xC00B0006,2580 MUI_FILE_NOT_LOADED = 0xC00B0006,
3774
3775 /// The user stopped resource enumeration.2581 /// The user stopped resource enumeration.
3776 RESOURCE_ENUM_USER_STOP = 0xC00B0007,2582 RESOURCE_ENUM_USER_STOP = 0xC00B0007,
3777
3778 /// The cluster node is not valid.2583 /// The cluster node is not valid.
3779 CLUSTER_INVALID_NODE = 0xC0130001,2584 CLUSTER_INVALID_NODE = 0xC0130001,
3780
3781 /// The cluster node already exists.2585 /// The cluster node already exists.
3782 CLUSTER_NODE_EXISTS = 0xC0130002,2586 CLUSTER_NODE_EXISTS = 0xC0130002,
3783
3784 /// A node is in the process of joining the cluster.2587 /// A node is in the process of joining the cluster.
3785 CLUSTER_JOIN_IN_PROGRESS = 0xC0130003,2588 CLUSTER_JOIN_IN_PROGRESS = 0xC0130003,
3786
3787 /// The cluster node was not found.2589 /// The cluster node was not found.
3788 CLUSTER_NODE_NOT_FOUND = 0xC0130004,2590 CLUSTER_NODE_NOT_FOUND = 0xC0130004,
3789
3790 /// The cluster local node information was not found.2591 /// The cluster local node information was not found.
3791 CLUSTER_LOCAL_NODE_NOT_FOUND = 0xC0130005,2592 CLUSTER_LOCAL_NODE_NOT_FOUND = 0xC0130005,
3792
3793 /// The cluster network already exists.2593 /// The cluster network already exists.
3794 CLUSTER_NETWORK_EXISTS = 0xC0130006,2594 CLUSTER_NETWORK_EXISTS = 0xC0130006,
3795
3796 /// The cluster network was not found.2595 /// The cluster network was not found.
3797 CLUSTER_NETWORK_NOT_FOUND = 0xC0130007,2596 CLUSTER_NETWORK_NOT_FOUND = 0xC0130007,
3798
3799 /// The cluster network interface already exists.2597 /// The cluster network interface already exists.
3800 CLUSTER_NETINTERFACE_EXISTS = 0xC0130008,2598 CLUSTER_NETINTERFACE_EXISTS = 0xC0130008,
3801
3802 /// The cluster network interface was not found.2599 /// The cluster network interface was not found.
3803 CLUSTER_NETINTERFACE_NOT_FOUND = 0xC0130009,2600 CLUSTER_NETINTERFACE_NOT_FOUND = 0xC0130009,
3804
3805 /// The cluster request is not valid for this object.2601 /// The cluster request is not valid for this object.
3806 CLUSTER_INVALID_REQUEST = 0xC013000A,2602 CLUSTER_INVALID_REQUEST = 0xC013000A,
3807
3808 /// The cluster network provider is not valid.2603 /// The cluster network provider is not valid.
3809 CLUSTER_INVALID_NETWORK_PROVIDER = 0xC013000B,2604 CLUSTER_INVALID_NETWORK_PROVIDER = 0xC013000B,
3810
3811 /// The cluster node is down.2605 /// The cluster node is down.
3812 CLUSTER_NODE_DOWN = 0xC013000C,2606 CLUSTER_NODE_DOWN = 0xC013000C,
3813
3814 /// The cluster node is not reachable.2607 /// The cluster node is not reachable.
3815 CLUSTER_NODE_UNREACHABLE = 0xC013000D,2608 CLUSTER_NODE_UNREACHABLE = 0xC013000D,
3816
3817 /// The cluster node is not a member of the cluster.2609 /// The cluster node is not a member of the cluster.
3818 CLUSTER_NODE_NOT_MEMBER = 0xC013000E,2610 CLUSTER_NODE_NOT_MEMBER = 0xC013000E,
3819
3820 /// A cluster join operation is not in progress.2611 /// A cluster join operation is not in progress.
3821 CLUSTER_JOIN_NOT_IN_PROGRESS = 0xC013000F,2612 CLUSTER_JOIN_NOT_IN_PROGRESS = 0xC013000F,
3822
3823 /// The cluster network is not valid.2613 /// The cluster network is not valid.
3824 CLUSTER_INVALID_NETWORK = 0xC0130010,2614 CLUSTER_INVALID_NETWORK = 0xC0130010,
3825
3826 /// No network adapters are available.2615 /// No network adapters are available.
3827 CLUSTER_NO_NET_ADAPTERS = 0xC0130011,2616 CLUSTER_NO_NET_ADAPTERS = 0xC0130011,
3828
3829 /// The cluster node is up.2617 /// The cluster node is up.
3830 CLUSTER_NODE_UP = 0xC0130012,2618 CLUSTER_NODE_UP = 0xC0130012,
3831
3832 /// The cluster node is paused.2619 /// The cluster node is paused.
3833 CLUSTER_NODE_PAUSED = 0xC0130013,2620 CLUSTER_NODE_PAUSED = 0xC0130013,
3834
3835 /// The cluster node is not paused.2621 /// The cluster node is not paused.
3836 CLUSTER_NODE_NOT_PAUSED = 0xC0130014,2622 CLUSTER_NODE_NOT_PAUSED = 0xC0130014,
3837
3838 /// No cluster security context is available.2623 /// No cluster security context is available.
3839 CLUSTER_NO_SECURITY_CONTEXT = 0xC0130015,2624 CLUSTER_NO_SECURITY_CONTEXT = 0xC0130015,
3840
3841 /// The cluster network is not configured for internal cluster communication.2625 /// The cluster network is not configured for internal cluster communication.
3842 CLUSTER_NETWORK_NOT_INTERNAL = 0xC0130016,2626 CLUSTER_NETWORK_NOT_INTERNAL = 0xC0130016,
3843
3844 /// The cluster node has been poisoned.2627 /// The cluster node has been poisoned.
3845 CLUSTER_POISONED = 0xC0130017,2628 CLUSTER_POISONED = 0xC0130017,
3846
3847 /// An attempt was made to run an invalid AML opcode.2629 /// An attempt was made to run an invalid AML opcode.
3848 ACPI_INVALID_OPCODE = 0xC0140001,2630 ACPI_INVALID_OPCODE = 0xC0140001,
3849
3850 /// The AML interpreter stack has overflowed.2631 /// The AML interpreter stack has overflowed.
3851 ACPI_STACK_OVERFLOW = 0xC0140002,2632 ACPI_STACK_OVERFLOW = 0xC0140002,
3852
3853 /// An inconsistent state has occurred.2633 /// An inconsistent state has occurred.
3854 ACPI_ASSERT_FAILED = 0xC0140003,2634 ACPI_ASSERT_FAILED = 0xC0140003,
3855
3856 /// An attempt was made to access an array outside its bounds.2635 /// An attempt was made to access an array outside its bounds.
3857 ACPI_INVALID_INDEX = 0xC0140004,2636 ACPI_INVALID_INDEX = 0xC0140004,
3858
3859 /// A required argument was not specified.2637 /// A required argument was not specified.
3860 ACPI_INVALID_ARGUMENT = 0xC0140005,2638 ACPI_INVALID_ARGUMENT = 0xC0140005,
3861
3862 /// A fatal error has occurred.2639 /// A fatal error has occurred.
3863 ACPI_FATAL = 0xC0140006,2640 ACPI_FATAL = 0xC0140006,
3864
3865 /// An invalid SuperName was specified.2641 /// An invalid SuperName was specified.
3866 ACPI_INVALID_SUPERNAME = 0xC0140007,2642 ACPI_INVALID_SUPERNAME = 0xC0140007,
3867
3868 /// An argument with an incorrect type was specified.2643 /// An argument with an incorrect type was specified.
3869 ACPI_INVALID_ARGTYPE = 0xC0140008,2644 ACPI_INVALID_ARGTYPE = 0xC0140008,
3870
3871 /// An object with an incorrect type was specified.2645 /// An object with an incorrect type was specified.
3872 ACPI_INVALID_OBJTYPE = 0xC0140009,2646 ACPI_INVALID_OBJTYPE = 0xC0140009,
3873
3874 /// A target with an incorrect type was specified.2647 /// A target with an incorrect type was specified.
3875 ACPI_INVALID_TARGETTYPE = 0xC014000A,2648 ACPI_INVALID_TARGETTYPE = 0xC014000A,
3876
3877 /// An incorrect number of arguments was specified.2649 /// An incorrect number of arguments was specified.
3878 ACPI_INCORRECT_ARGUMENT_COUNT = 0xC014000B,2650 ACPI_INCORRECT_ARGUMENT_COUNT = 0xC014000B,
3879
3880 /// An address failed to translate.2651 /// An address failed to translate.
3881 ACPI_ADDRESS_NOT_MAPPED = 0xC014000C,2652 ACPI_ADDRESS_NOT_MAPPED = 0xC014000C,
3882
3883 /// An incorrect event type was specified.2653 /// An incorrect event type was specified.
3884 ACPI_INVALID_EVENTTYPE = 0xC014000D,2654 ACPI_INVALID_EVENTTYPE = 0xC014000D,
3885
3886 /// A handler for the target already exists.2655 /// A handler for the target already exists.
3887 ACPI_HANDLER_COLLISION = 0xC014000E,2656 ACPI_HANDLER_COLLISION = 0xC014000E,
3888
3889 /// Invalid data for the target was specified.2657 /// Invalid data for the target was specified.
3890 ACPI_INVALID_DATA = 0xC014000F,2658 ACPI_INVALID_DATA = 0xC014000F,
3891
3892 /// An invalid region for the target was specified.2659 /// An invalid region for the target was specified.
3893 ACPI_INVALID_REGION = 0xC0140010,2660 ACPI_INVALID_REGION = 0xC0140010,
3894
3895 /// An attempt was made to access a field outside the defined range.2661 /// An attempt was made to access a field outside the defined range.
3896 ACPI_INVALID_ACCESS_SIZE = 0xC0140011,2662 ACPI_INVALID_ACCESS_SIZE = 0xC0140011,
3897
3898 /// The global system lock could not be acquired.2663 /// The global system lock could not be acquired.
3899 ACPI_ACQUIRE_GLOBAL_LOCK = 0xC0140012,2664 ACPI_ACQUIRE_GLOBAL_LOCK = 0xC0140012,
3900
3901 /// An attempt was made to reinitialize the ACPI subsystem.2665 /// An attempt was made to reinitialize the ACPI subsystem.
3902 ACPI_ALREADY_INITIALIZED = 0xC0140013,2666 ACPI_ALREADY_INITIALIZED = 0xC0140013,
3903
3904 /// The ACPI subsystem has not been initialized.2667 /// The ACPI subsystem has not been initialized.
3905 ACPI_NOT_INITIALIZED = 0xC0140014,2668 ACPI_NOT_INITIALIZED = 0xC0140014,
3906
3907 /// An incorrect mutex was specified.2669 /// An incorrect mutex was specified.
3908 ACPI_INVALID_MUTEX_LEVEL = 0xC0140015,2670 ACPI_INVALID_MUTEX_LEVEL = 0xC0140015,
3909
3910 /// The mutex is not currently owned.2671 /// The mutex is not currently owned.
3911 ACPI_MUTEX_NOT_OWNED = 0xC0140016,2672 ACPI_MUTEX_NOT_OWNED = 0xC0140016,
3912
3913 /// An attempt was made to access the mutex by a process that was not the owner.2673 /// An attempt was made to access the mutex by a process that was not the owner.
3914 ACPI_MUTEX_NOT_OWNER = 0xC0140017,2674 ACPI_MUTEX_NOT_OWNER = 0xC0140017,
3915
3916 /// An error occurred during an access to region space.2675 /// An error occurred during an access to region space.
3917 ACPI_RS_ACCESS = 0xC0140018,2676 ACPI_RS_ACCESS = 0xC0140018,
3918
3919 /// An attempt was made to use an incorrect table.2677 /// An attempt was made to use an incorrect table.
3920 ACPI_INVALID_TABLE = 0xC0140019,2678 ACPI_INVALID_TABLE = 0xC0140019,
3921
3922 /// The registration of an ACPI event failed.2679 /// The registration of an ACPI event failed.
3923 ACPI_REG_HANDLER_FAILED = 0xC0140020,2680 ACPI_REG_HANDLER_FAILED = 0xC0140020,
3924
3925 /// An ACPI power object failed to transition state.2681 /// An ACPI power object failed to transition state.
3926 ACPI_POWER_REQUEST_FAILED = 0xC0140021,2682 ACPI_POWER_REQUEST_FAILED = 0xC0140021,
3927
3928 /// The requested section is not present in the activation context.2683 /// The requested section is not present in the activation context.
3929 SXS_SECTION_NOT_FOUND = 0xC0150001,2684 SXS_SECTION_NOT_FOUND = 0xC0150001,
3930
3931 /// Windows was unble to process the application binding information.2685 /// Windows was unble to process the application binding information.
3932 /// Refer to the system event log for further information.2686 /// Refer to the system event log for further information.
3933 SXS_CANT_GEN_ACTCTX = 0xC0150002,2687 SXS_CANT_GEN_ACTCTX = 0xC0150002,
3934
3935 /// The application binding data format is invalid.2688 /// The application binding data format is invalid.
3936 SXS_INVALID_ACTCTXDATA_FORMAT = 0xC0150003,2689 SXS_INVALID_ACTCTXDATA_FORMAT = 0xC0150003,
3937
3938 /// The referenced assembly is not installed on the system.2690 /// The referenced assembly is not installed on the system.
3939 SXS_ASSEMBLY_NOT_FOUND = 0xC0150004,2691 SXS_ASSEMBLY_NOT_FOUND = 0xC0150004,
3940
3941 /// The manifest file does not begin with the required tag and format information.2692 /// The manifest file does not begin with the required tag and format information.
3942 SXS_MANIFEST_FORMAT_ERROR = 0xC0150005,2693 SXS_MANIFEST_FORMAT_ERROR = 0xC0150005,
3943
3944 /// The manifest file contains one or more syntax errors.2694 /// The manifest file contains one or more syntax errors.
3945 SXS_MANIFEST_PARSE_ERROR = 0xC0150006,2695 SXS_MANIFEST_PARSE_ERROR = 0xC0150006,
3946
3947 /// The application attempted to activate a disabled activation context.2696 /// The application attempted to activate a disabled activation context.
3948 SXS_ACTIVATION_CONTEXT_DISABLED = 0xC0150007,2697 SXS_ACTIVATION_CONTEXT_DISABLED = 0xC0150007,
3949
3950 /// The requested lookup key was not found in any active activation context.2698 /// The requested lookup key was not found in any active activation context.
3951 SXS_KEY_NOT_FOUND = 0xC0150008,2699 SXS_KEY_NOT_FOUND = 0xC0150008,
3952
3953 /// A component version required by the application conflicts with another component version that is already active.2700 /// A component version required by the application conflicts with another component version that is already active.
3954 SXS_VERSION_CONFLICT = 0xC0150009,2701 SXS_VERSION_CONFLICT = 0xC0150009,
3955
3956 /// The type requested activation context section does not match the query API used.2702 /// The type requested activation context section does not match the query API used.
3957 SXS_WRONG_SECTION_TYPE = 0xC015000A,2703 SXS_WRONG_SECTION_TYPE = 0xC015000A,
3958
3959 /// Lack of system resources has required isolated activation to be disabled for the current thread of execution.2704 /// Lack of system resources has required isolated activation to be disabled for the current thread of execution.
3960 SXS_THREAD_QUERIES_DISABLED = 0xC015000B,2705 SXS_THREAD_QUERIES_DISABLED = 0xC015000B,
3961
3962 /// The referenced assembly could not be found.2706 /// The referenced assembly could not be found.
3963 SXS_ASSEMBLY_MISSING = 0xC015000C,2707 SXS_ASSEMBLY_MISSING = 0xC015000C,
3964
3965 /// An attempt to set the process default activation context failed because the process default activation context was already set.2708 /// An attempt to set the process default activation context failed because the process default activation context was already set.
3966 SXS_PROCESS_DEFAULT_ALREADY_SET = 0xC015000E,2709 SXS_PROCESS_DEFAULT_ALREADY_SET = 0xC015000E,
3967
3968 /// The activation context being deactivated is not the most recently activated one.2710 /// The activation context being deactivated is not the most recently activated one.
3969 SXS_EARLY_DEACTIVATION = 0xC015000F,2711 SXS_EARLY_DEACTIVATION = 0xC015000F,
3970
3971 /// The activation context being deactivated is not active for the current thread of execution.2712 /// The activation context being deactivated is not active for the current thread of execution.
3972 SXS_INVALID_DEACTIVATION = 0xC0150010,2713 SXS_INVALID_DEACTIVATION = 0xC0150010,
3973
3974 /// The activation context being deactivated has already been deactivated.2714 /// The activation context being deactivated has already been deactivated.
3975 SXS_MULTIPLE_DEACTIVATION = 0xC0150011,2715 SXS_MULTIPLE_DEACTIVATION = 0xC0150011,
3976
3977 /// The activation context of the system default assembly could not be generated.2716 /// The activation context of the system default assembly could not be generated.
3978 SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY = 0xC0150012,2717 SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY = 0xC0150012,
3979
3980 /// A component used by the isolation facility has requested that the process be terminated.2718 /// A component used by the isolation facility has requested that the process be terminated.
3981 SXS_PROCESS_TERMINATION_REQUESTED = 0xC0150013,2719 SXS_PROCESS_TERMINATION_REQUESTED = 0xC0150013,
3982
3983 /// The activation context activation stack for the running thread of execution is corrupt.2720 /// The activation context activation stack for the running thread of execution is corrupt.
3984 SXS_CORRUPT_ACTIVATION_STACK = 0xC0150014,2721 SXS_CORRUPT_ACTIVATION_STACK = 0xC0150014,
3985
3986 /// The application isolation metadata for this process or thread has become corrupt.2722 /// The application isolation metadata for this process or thread has become corrupt.
3987 SXS_CORRUPTION = 0xC0150015,2723 SXS_CORRUPTION = 0xC0150015,
3988
3989 /// The value of an attribute in an identity is not within the legal range.2724 /// The value of an attribute in an identity is not within the legal range.
3990 SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE = 0xC0150016,2725 SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE = 0xC0150016,
3991
3992 /// The name of an attribute in an identity is not within the legal range.2726 /// The name of an attribute in an identity is not within the legal range.
3993 SXS_INVALID_IDENTITY_ATTRIBUTE_NAME = 0xC0150017,2727 SXS_INVALID_IDENTITY_ATTRIBUTE_NAME = 0xC0150017,
3994
3995 /// An identity contains two definitions for the same attribute.2728 /// An identity contains two definitions for the same attribute.
3996 SXS_IDENTITY_DUPLICATE_ATTRIBUTE = 0xC0150018,2729 SXS_IDENTITY_DUPLICATE_ATTRIBUTE = 0xC0150018,
3997
3998 /// The identity string is malformed.2730 /// The identity string is malformed.
3999 /// This might be due to a trailing comma, more than two unnamed attributes, a missing attribute name, or a missing attribute value.2731 /// This might be due to a trailing comma, more than two unnamed attributes, a missing attribute name, or a missing attribute value.
4000 SXS_IDENTITY_PARSE_ERROR = 0xC0150019,2732 SXS_IDENTITY_PARSE_ERROR = 0xC0150019,
4001
4002 /// The component store has become corrupted.2733 /// The component store has become corrupted.
4003 SXS_COMPONENT_STORE_CORRUPT = 0xC015001A,2734 SXS_COMPONENT_STORE_CORRUPT = 0xC015001A,
4004
4005 /// A component's file does not match the verification information present in the component manifest.2735 /// A component's file does not match the verification information present in the component manifest.
4006 SXS_FILE_HASH_MISMATCH = 0xC015001B,2736 SXS_FILE_HASH_MISMATCH = 0xC015001B,
4007
4008 /// The identities of the manifests are identical, but their contents are different.2737 /// The identities of the manifests are identical, but their contents are different.
4009 SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT = 0xC015001C,2738 SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT = 0xC015001C,
4010
4011 /// The component identities are different.2739 /// The component identities are different.
4012 SXS_IDENTITIES_DIFFERENT = 0xC015001D,2740 SXS_IDENTITIES_DIFFERENT = 0xC015001D,
4013
4014 /// The assembly is not a deployment.2741 /// The assembly is not a deployment.
4015 SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT = 0xC015001E,2742 SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT = 0xC015001E,
4016
4017 /// The file is not a part of the assembly.2743 /// The file is not a part of the assembly.
4018 SXS_FILE_NOT_PART_OF_ASSEMBLY = 0xC015001F,2744 SXS_FILE_NOT_PART_OF_ASSEMBLY = 0xC015001F,
4019
4020 /// An advanced installer failed during setup or servicing.2745 /// An advanced installer failed during setup or servicing.
4021 ADVANCED_INSTALLER_FAILED = 0xC0150020,2746 ADVANCED_INSTALLER_FAILED = 0xC0150020,
4022
4023 /// The character encoding in the XML declaration did not match the encoding used in the document.2747 /// The character encoding in the XML declaration did not match the encoding used in the document.
4024 XML_ENCODING_MISMATCH = 0xC0150021,2748 XML_ENCODING_MISMATCH = 0xC0150021,
4025
4026 /// The size of the manifest exceeds the maximum allowed.2749 /// The size of the manifest exceeds the maximum allowed.
4027 SXS_MANIFEST_TOO_BIG = 0xC0150022,2750 SXS_MANIFEST_TOO_BIG = 0xC0150022,
4028
4029 /// The setting is not registered.2751 /// The setting is not registered.
4030 SXS_SETTING_NOT_REGISTERED = 0xC0150023,2752 SXS_SETTING_NOT_REGISTERED = 0xC0150023,
4031
4032 /// One or more required transaction members are not present.2753 /// One or more required transaction members are not present.
4033 SXS_TRANSACTION_CLOSURE_INCOMPLETE = 0xC0150024,2754 SXS_TRANSACTION_CLOSURE_INCOMPLETE = 0xC0150024,
4034
4035 /// The SMI primitive installer failed during setup or servicing.2755 /// The SMI primitive installer failed during setup or servicing.
4036 SMI_PRIMITIVE_INSTALLER_FAILED = 0xC0150025,2756 SMI_PRIMITIVE_INSTALLER_FAILED = 0xC0150025,
4037
4038 /// A generic command executable returned a result that indicates failure.2757 /// A generic command executable returned a result that indicates failure.
4039 GENERIC_COMMAND_FAILED = 0xC0150026,2758 GENERIC_COMMAND_FAILED = 0xC0150026,
4040
4041 /// A component is missing file verification information in its manifest.2759 /// A component is missing file verification information in its manifest.
4042 SXS_FILE_HASH_MISSING = 0xC0150027,2760 SXS_FILE_HASH_MISSING = 0xC0150027,
4043
4044 /// The function attempted to use a name that is reserved for use by another transaction.2761 /// The function attempted to use a name that is reserved for use by another transaction.
4045 TRANSACTIONAL_CONFLICT = 0xC0190001,2762 TRANSACTIONAL_CONFLICT = 0xC0190001,
4046
4047 /// The transaction handle associated with this operation is invalid.2763 /// The transaction handle associated with this operation is invalid.
4048 INVALID_TRANSACTION = 0xC0190002,2764 INVALID_TRANSACTION = 0xC0190002,
4049
4050 /// The requested operation was made in the context of a transaction that is no longer active.2765 /// The requested operation was made in the context of a transaction that is no longer active.
4051 TRANSACTION_NOT_ACTIVE = 0xC0190003,2766 TRANSACTION_NOT_ACTIVE = 0xC0190003,
4052
4053 /// The transaction manager was unable to be successfully initialized. Transacted operations are not supported.2767 /// The transaction manager was unable to be successfully initialized. Transacted operations are not supported.
4054 TM_INITIALIZATION_FAILED = 0xC0190004,2768 TM_INITIALIZATION_FAILED = 0xC0190004,
4055
4056 /// Transaction support within the specified file system resource manager was not started or was shut down due to an error.2769 /// Transaction support within the specified file system resource manager was not started or was shut down due to an error.
4057 RM_NOT_ACTIVE = 0xC0190005,2770 RM_NOT_ACTIVE = 0xC0190005,
4058
4059 /// The metadata of the resource manager has been corrupted. The resource manager will not function.2771 /// The metadata of the resource manager has been corrupted. The resource manager will not function.
4060 RM_METADATA_CORRUPT = 0xC0190006,2772 RM_METADATA_CORRUPT = 0xC0190006,
4061
4062 /// The resource manager attempted to prepare a transaction that it has not successfully joined.2773 /// The resource manager attempted to prepare a transaction that it has not successfully joined.
4063 TRANSACTION_NOT_JOINED = 0xC0190007,2774 TRANSACTION_NOT_JOINED = 0xC0190007,
4064
4065 /// The specified directory does not contain a file system resource manager.2775 /// The specified directory does not contain a file system resource manager.
4066 DIRECTORY_NOT_RM = 0xC0190008,2776 DIRECTORY_NOT_RM = 0xC0190008,
4067
4068 /// The remote server or share does not support transacted file operations.2777 /// The remote server or share does not support transacted file operations.
4069 TRANSACTIONS_UNSUPPORTED_REMOTE = 0xC019000A,2778 TRANSACTIONS_UNSUPPORTED_REMOTE = 0xC019000A,
4070
4071 /// The requested log size for the file system resource manager is invalid.2779 /// The requested log size for the file system resource manager is invalid.
4072 LOG_RESIZE_INVALID_SIZE = 0xC019000B,2780 LOG_RESIZE_INVALID_SIZE = 0xC019000B,
4073
4074 /// The remote server sent mismatching version number or Fid for a file opened with transactions.2781 /// The remote server sent mismatching version number or Fid for a file opened with transactions.
4075 REMOTE_FILE_VERSION_MISMATCH = 0xC019000C,2782 REMOTE_FILE_VERSION_MISMATCH = 0xC019000C,
4076
4077 /// The resource manager tried to register a protocol that already exists.2783 /// The resource manager tried to register a protocol that already exists.
4078 CRM_PROTOCOL_ALREADY_EXISTS = 0xC019000F,2784 CRM_PROTOCOL_ALREADY_EXISTS = 0xC019000F,
4079
4080 /// The attempt to propagate the transaction failed.2785 /// The attempt to propagate the transaction failed.
4081 TRANSACTION_PROPAGATION_FAILED = 0xC0190010,2786 TRANSACTION_PROPAGATION_FAILED = 0xC0190010,
4082
4083 /// The requested propagation protocol was not registered as a CRM.2787 /// The requested propagation protocol was not registered as a CRM.
4084 CRM_PROTOCOL_NOT_FOUND = 0xC0190011,2788 CRM_PROTOCOL_NOT_FOUND = 0xC0190011,
4085
4086 /// The transaction object already has a superior enlistment, and the caller attempted an operation that would have created a new superior. Only a single superior enlistment is allowed.2789 /// The transaction object already has a superior enlistment, and the caller attempted an operation that would have created a new superior. Only a single superior enlistment is allowed.
4087 TRANSACTION_SUPERIOR_EXISTS = 0xC0190012,2790 TRANSACTION_SUPERIOR_EXISTS = 0xC0190012,
4088
4089 /// The requested operation is not valid on the transaction object in its current state.2791 /// The requested operation is not valid on the transaction object in its current state.
4090 TRANSACTION_REQUEST_NOT_VALID = 0xC0190013,2792 TRANSACTION_REQUEST_NOT_VALID = 0xC0190013,
4091
4092 /// The caller has called a response API, but the response is not expected because the transaction manager did not issue the corresponding request to the caller.2793 /// The caller has called a response API, but the response is not expected because the transaction manager did not issue the corresponding request to the caller.
4093 TRANSACTION_NOT_REQUESTED = 0xC0190014,2794 TRANSACTION_NOT_REQUESTED = 0xC0190014,
4094
4095 /// It is too late to perform the requested operation, because the transaction has already been aborted.2795 /// It is too late to perform the requested operation, because the transaction has already been aborted.
4096 TRANSACTION_ALREADY_ABORTED = 0xC0190015,2796 TRANSACTION_ALREADY_ABORTED = 0xC0190015,
4097
4098 /// It is too late to perform the requested operation, because the transaction has already been committed.2797 /// It is too late to perform the requested operation, because the transaction has already been committed.
4099 TRANSACTION_ALREADY_COMMITTED = 0xC0190016,2798 TRANSACTION_ALREADY_COMMITTED = 0xC0190016,
4100
4101 /// The buffer passed in to NtPushTransaction or NtPullTransaction is not in a valid format.2799 /// The buffer passed in to NtPushTransaction or NtPullTransaction is not in a valid format.
4102 TRANSACTION_INVALID_MARSHALL_BUFFER = 0xC0190017,2800 TRANSACTION_INVALID_MARSHALL_BUFFER = 0xC0190017,
4103
4104 /// The current transaction context associated with the thread is not a valid handle to a transaction object.2801 /// The current transaction context associated with the thread is not a valid handle to a transaction object.
4105 CURRENT_TRANSACTION_NOT_VALID = 0xC0190018,2802 CURRENT_TRANSACTION_NOT_VALID = 0xC0190018,
4106
4107 /// An attempt to create space in the transactional resource manager's log failed.2803 /// An attempt to create space in the transactional resource manager's log failed.
4108 /// The failure status has been recorded in the event log.2804 /// The failure status has been recorded in the event log.
4109 LOG_GROWTH_FAILED = 0xC0190019,2805 LOG_GROWTH_FAILED = 0xC0190019,
4110
4111 /// The object (file, stream, or link) that corresponds to the handle has been deleted by a transaction savepoint rollback.2806 /// The object (file, stream, or link) that corresponds to the handle has been deleted by a transaction savepoint rollback.
4112 OBJECT_NO_LONGER_EXISTS = 0xC0190021,2807 OBJECT_NO_LONGER_EXISTS = 0xC0190021,
4113
4114 /// The specified file miniversion was not found for this transacted file open.2808 /// The specified file miniversion was not found for this transacted file open.
4115 STREAM_MINIVERSION_NOT_FOUND = 0xC0190022,2809 STREAM_MINIVERSION_NOT_FOUND = 0xC0190022,
4116
4117 /// The specified file miniversion was found but has been invalidated.2810 /// The specified file miniversion was found but has been invalidated.
4118 /// The most likely cause is a transaction savepoint rollback.2811 /// The most likely cause is a transaction savepoint rollback.
4119 STREAM_MINIVERSION_NOT_VALID = 0xC0190023,2812 STREAM_MINIVERSION_NOT_VALID = 0xC0190023,
4120
4121 /// A miniversion can be opened only in the context of the transaction that created it.2813 /// A miniversion can be opened only in the context of the transaction that created it.
4122 MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION = 0xC0190024,2814 MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION = 0xC0190024,
4123
4124 /// It is not possible to open a miniversion with modify access.2815 /// It is not possible to open a miniversion with modify access.
4125 CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT = 0xC0190025,2816 CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT = 0xC0190025,
4126
4127 /// It is not possible to create any more miniversions for this stream.2817 /// It is not possible to create any more miniversions for this stream.
4128 CANT_CREATE_MORE_STREAM_MINIVERSIONS = 0xC0190026,2818 CANT_CREATE_MORE_STREAM_MINIVERSIONS = 0xC0190026,
4129
4130 /// The handle has been invalidated by a transaction.2819 /// The handle has been invalidated by a transaction.
4131 /// The most likely cause is the presence of memory mapping on a file or an open handle when the transaction ended or rolled back to savepoint.2820 /// The most likely cause is the presence of memory mapping on a file or an open handle when the transaction ended or rolled back to savepoint.
4132 HANDLE_NO_LONGER_VALID = 0xC0190028,2821 HANDLE_NO_LONGER_VALID = 0xC0190028,
4133
4134 /// The log data is corrupt.2822 /// The log data is corrupt.
4135 LOG_CORRUPTION_DETECTED = 0xC0190030,2823 LOG_CORRUPTION_DETECTED = 0xC0190030,
4136
4137 /// The transaction outcome is unavailable because the resource manager responsible for it is disconnected.2824 /// The transaction outcome is unavailable because the resource manager responsible for it is disconnected.
4138 RM_DISCONNECTED = 0xC0190032,2825 RM_DISCONNECTED = 0xC0190032,
4139
4140 /// The request was rejected because the enlistment in question is not a superior enlistment.2826 /// The request was rejected because the enlistment in question is not a superior enlistment.
4141 ENLISTMENT_NOT_SUPERIOR = 0xC0190033,2827 ENLISTMENT_NOT_SUPERIOR = 0xC0190033,
4142
4143 /// The file cannot be opened in a transaction because its identity depends on the outcome of an unresolved transaction.2828 /// The file cannot be opened in a transaction because its identity depends on the outcome of an unresolved transaction.
4144 FILE_IDENTITY_NOT_PERSISTENT = 0xC0190036,2829 FILE_IDENTITY_NOT_PERSISTENT = 0xC0190036,
4145
4146 /// The operation cannot be performed because another transaction is depending on this property not changing.2830 /// The operation cannot be performed because another transaction is depending on this property not changing.
4147 CANT_BREAK_TRANSACTIONAL_DEPENDENCY = 0xC0190037,2831 CANT_BREAK_TRANSACTIONAL_DEPENDENCY = 0xC0190037,
4148
4149 /// The operation would involve a single file with two transactional resource managers and is, therefore, not allowed.2832 /// The operation would involve a single file with two transactional resource managers and is, therefore, not allowed.
4150 CANT_CROSS_RM_BOUNDARY = 0xC0190038,2833 CANT_CROSS_RM_BOUNDARY = 0xC0190038,
4151
4152 /// The $Txf directory must be empty for this operation to succeed.2834 /// The $Txf directory must be empty for this operation to succeed.
4153 TXF_DIR_NOT_EMPTY = 0xC0190039,2835 TXF_DIR_NOT_EMPTY = 0xC0190039,
4154
4155 /// The operation would leave a transactional resource manager in an inconsistent state and is therefore not allowed.2836 /// The operation would leave a transactional resource manager in an inconsistent state and is therefore not allowed.
4156 INDOUBT_TRANSACTIONS_EXIST = 0xC019003A,2837 INDOUBT_TRANSACTIONS_EXIST = 0xC019003A,
4157
4158 /// The operation could not be completed because the transaction manager does not have a log.2838 /// The operation could not be completed because the transaction manager does not have a log.
4159 TM_VOLATILE = 0xC019003B,2839 TM_VOLATILE = 0xC019003B,
4160
4161 /// A rollback could not be scheduled because a previously scheduled rollback has already executed or been queued for execution.2840 /// A rollback could not be scheduled because a previously scheduled rollback has already executed or been queued for execution.
4162 ROLLBACK_TIMER_EXPIRED = 0xC019003C,2841 ROLLBACK_TIMER_EXPIRED = 0xC019003C,
4163
4164 /// The transactional metadata attribute on the file or directory %hs is corrupt and unreadable.2842 /// The transactional metadata attribute on the file or directory %hs is corrupt and unreadable.
4165 TXF_ATTRIBUTE_CORRUPT = 0xC019003D,2843 TXF_ATTRIBUTE_CORRUPT = 0xC019003D,
4166
4167 /// The encryption operation could not be completed because a transaction is active.2844 /// The encryption operation could not be completed because a transaction is active.
4168 EFS_NOT_ALLOWED_IN_TRANSACTION = 0xC019003E,2845 EFS_NOT_ALLOWED_IN_TRANSACTION = 0xC019003E,
4169
4170 /// This object is not allowed to be opened in a transaction.2846 /// This object is not allowed to be opened in a transaction.
4171 TRANSACTIONAL_OPEN_NOT_ALLOWED = 0xC019003F,2847 TRANSACTIONAL_OPEN_NOT_ALLOWED = 0xC019003F,
4172
4173 /// Memory mapping (creating a mapped section) a remote file under a transaction is not supported.2848 /// Memory mapping (creating a mapped section) a remote file under a transaction is not supported.
4174 TRANSACTED_MAPPING_UNSUPPORTED_REMOTE = 0xC0190040,2849 TRANSACTED_MAPPING_UNSUPPORTED_REMOTE = 0xC0190040,
4175
4176 /// Promotion was required to allow the resource manager to enlist, but the transaction was set to disallow it.2850 /// Promotion was required to allow the resource manager to enlist, but the transaction was set to disallow it.
4177 TRANSACTION_REQUIRED_PROMOTION = 0xC0190043,2851 TRANSACTION_REQUIRED_PROMOTION = 0xC0190043,
4178
4179 /// This file is open for modification in an unresolved transaction and can be opened for execute only by a transacted reader.2852 /// This file is open for modification in an unresolved transaction and can be opened for execute only by a transacted reader.
4180 CANNOT_EXECUTE_FILE_IN_TRANSACTION = 0xC0190044,2853 CANNOT_EXECUTE_FILE_IN_TRANSACTION = 0xC0190044,
4181
4182 /// The request to thaw frozen transactions was ignored because transactions were not previously frozen.2854 /// The request to thaw frozen transactions was ignored because transactions were not previously frozen.
4183 TRANSACTIONS_NOT_FROZEN = 0xC0190045,2855 TRANSACTIONS_NOT_FROZEN = 0xC0190045,
4184
4185 /// Transactions cannot be frozen because a freeze is already in progress.2856 /// Transactions cannot be frozen because a freeze is already in progress.
4186 TRANSACTION_FREEZE_IN_PROGRESS = 0xC0190046,2857 TRANSACTION_FREEZE_IN_PROGRESS = 0xC0190046,
4187
4188 /// The target volume is not a snapshot volume.2858 /// The target volume is not a snapshot volume.
4189 /// This operation is valid only on a volume mounted as a snapshot.2859 /// This operation is valid only on a volume mounted as a snapshot.
4190 NOT_SNAPSHOT_VOLUME = 0xC0190047,2860 NOT_SNAPSHOT_VOLUME = 0xC0190047,
4191
4192 /// The savepoint operation failed because files are open on the transaction, which is not permitted.2861 /// The savepoint operation failed because files are open on the transaction, which is not permitted.
4193 NO_SAVEPOINT_WITH_OPEN_FILES = 0xC0190048,2862 NO_SAVEPOINT_WITH_OPEN_FILES = 0xC0190048,
4194
4195 /// The sparse operation could not be completed because a transaction is active on the file.2863 /// The sparse operation could not be completed because a transaction is active on the file.
4196 SPARSE_NOT_ALLOWED_IN_TRANSACTION = 0xC0190049,2864 SPARSE_NOT_ALLOWED_IN_TRANSACTION = 0xC0190049,
4197
4198 /// The call to create a transaction manager object failed because the Tm Identity that is stored in the log file does not match the Tm Identity that was passed in as an argument.2865 /// The call to create a transaction manager object failed because the Tm Identity that is stored in the log file does not match the Tm Identity that was passed in as an argument.
4199 TM_IDENTITY_MISMATCH = 0xC019004A,2866 TM_IDENTITY_MISMATCH = 0xC019004A,
4200
4201 /// I/O was attempted on a section object that has been floated as a result of a transaction ending. There is no valid data.2867 /// I/O was attempted on a section object that has been floated as a result of a transaction ending. There is no valid data.
4202 FLOATED_SECTION = 0xC019004B,2868 FLOATED_SECTION = 0xC019004B,
4203
4204 /// The transactional resource manager cannot currently accept transacted work due to a transient condition, such as low resources.2869 /// The transactional resource manager cannot currently accept transacted work due to a transient condition, such as low resources.
4205 CANNOT_ACCEPT_TRANSACTED_WORK = 0xC019004C,2870 CANNOT_ACCEPT_TRANSACTED_WORK = 0xC019004C,
4206
4207 /// The transactional resource manager had too many transactions outstanding that could not be aborted.2871 /// The transactional resource manager had too many transactions outstanding that could not be aborted.
4208 /// The transactional resource manager has been shut down.2872 /// The transactional resource manager has been shut down.
4209 CANNOT_ABORT_TRANSACTIONS = 0xC019004D,2873 CANNOT_ABORT_TRANSACTIONS = 0xC019004D,
4210
4211 /// The specified transaction was unable to be opened because it was not found.2874 /// The specified transaction was unable to be opened because it was not found.
4212 TRANSACTION_NOT_FOUND = 0xC019004E,2875 TRANSACTION_NOT_FOUND = 0xC019004E,
4213
4214 /// The specified resource manager was unable to be opened because it was not found.2876 /// The specified resource manager was unable to be opened because it was not found.
4215 RESOURCEMANAGER_NOT_FOUND = 0xC019004F,2877 RESOURCEMANAGER_NOT_FOUND = 0xC019004F,
4216
4217 /// The specified enlistment was unable to be opened because it was not found.2878 /// The specified enlistment was unable to be opened because it was not found.
4218 ENLISTMENT_NOT_FOUND = 0xC0190050,2879 ENLISTMENT_NOT_FOUND = 0xC0190050,
4219
4220 /// The specified transaction manager was unable to be opened because it was not found.2880 /// The specified transaction manager was unable to be opened because it was not found.
4221 TRANSACTIONMANAGER_NOT_FOUND = 0xC0190051,2881 TRANSACTIONMANAGER_NOT_FOUND = 0xC0190051,
4222
4223 /// The specified resource manager was unable to create an enlistment because its associated transaction manager is not online.2882 /// The specified resource manager was unable to create an enlistment because its associated transaction manager is not online.
4224 TRANSACTIONMANAGER_NOT_ONLINE = 0xC0190052,2883 TRANSACTIONMANAGER_NOT_ONLINE = 0xC0190052,
4225
4226 /// The specified transaction manager was unable to create the objects contained in its log file in the Ob namespace.2884 /// The specified transaction manager was unable to create the objects contained in its log file in the Ob namespace.
4227 /// Therefore, the transaction manager was unable to recover.2885 /// Therefore, the transaction manager was unable to recover.
4228 TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION = 0xC0190053,2886 TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION = 0xC0190053,
4229
4230 /// The call to create a superior enlistment on this transaction object could not be completed because the transaction object specified for the enlistment is a subordinate branch of the transaction.2887 /// The call to create a superior enlistment on this transaction object could not be completed because the transaction object specified for the enlistment is a subordinate branch of the transaction.
4231 /// Only the root of the transaction can be enlisted as a superior.2888 /// Only the root of the transaction can be enlisted as a superior.
4232 TRANSACTION_NOT_ROOT = 0xC0190054,2889 TRANSACTION_NOT_ROOT = 0xC0190054,
4233
4234 /// Because the associated transaction manager or resource manager has been closed, the handle is no longer valid.2890 /// Because the associated transaction manager or resource manager has been closed, the handle is no longer valid.
4235 TRANSACTION_OBJECT_EXPIRED = 0xC0190055,2891 TRANSACTION_OBJECT_EXPIRED = 0xC0190055,
4236
4237 /// The compression operation could not be completed because a transaction is active on the file.2892 /// The compression operation could not be completed because a transaction is active on the file.
4238 COMPRESSION_NOT_ALLOWED_IN_TRANSACTION = 0xC0190056,2893 COMPRESSION_NOT_ALLOWED_IN_TRANSACTION = 0xC0190056,
4239
4240 /// The specified operation could not be performed on this superior enlistment because the enlistment was not created with the corresponding completion response in the NotificationMask.2894 /// The specified operation could not be performed on this superior enlistment because the enlistment was not created with the corresponding completion response in the NotificationMask.
4241 TRANSACTION_RESPONSE_NOT_ENLISTED = 0xC0190057,2895 TRANSACTION_RESPONSE_NOT_ENLISTED = 0xC0190057,
4242
4243 /// The specified operation could not be performed because the record to be logged was too long.2896 /// The specified operation could not be performed because the record to be logged was too long.
4244 /// This can occur because either there are too many enlistments on this transaction or the combined RecoveryInformation being logged on behalf of those enlistments is too long.2897 /// This can occur because either there are too many enlistments on this transaction or the combined RecoveryInformation being logged on behalf of those enlistments is too long.
4245 TRANSACTION_RECORD_TOO_LONG = 0xC0190058,2898 TRANSACTION_RECORD_TOO_LONG = 0xC0190058,
4246
4247 /// The link-tracking operation could not be completed because a transaction is active.2899 /// The link-tracking operation could not be completed because a transaction is active.
4248 NO_LINK_TRACKING_IN_TRANSACTION = 0xC0190059,2900 NO_LINK_TRACKING_IN_TRANSACTION = 0xC0190059,
4249
4250 /// This operation cannot be performed in a transaction.2901 /// This operation cannot be performed in a transaction.
4251 OPERATION_NOT_SUPPORTED_IN_TRANSACTION = 0xC019005A,2902 OPERATION_NOT_SUPPORTED_IN_TRANSACTION = 0xC019005A,
4252
4253 /// The kernel transaction manager had to abort or forget the transaction because it blocked forward progress.2903 /// The kernel transaction manager had to abort or forget the transaction because it blocked forward progress.
4254 TRANSACTION_INTEGRITY_VIOLATED = 0xC019005B,2904 TRANSACTION_INTEGRITY_VIOLATED = 0xC019005B,
4255
4256 /// The handle is no longer properly associated with its transaction.2905 /// The handle is no longer properly associated with its transaction.
4257 /// It might have been opened in a transactional resource manager that was subsequently forced to restart. Please close the handle and open a new one.2906 /// It might have been opened in a transactional resource manager that was subsequently forced to restart. Please close the handle and open a new one.
4258 EXPIRED_HANDLE = 0xC0190060,2907 EXPIRED_HANDLE = 0xC0190060,
4259
4260 /// The specified operation could not be performed because the resource manager is not enlisted in the transaction.2908 /// The specified operation could not be performed because the resource manager is not enlisted in the transaction.
4261 TRANSACTION_NOT_ENLISTED = 0xC0190061,2909 TRANSACTION_NOT_ENLISTED = 0xC0190061,
4262
4263 /// The log service found an invalid log sector.2910 /// The log service found an invalid log sector.
4264 LOG_SECTOR_INVALID = 0xC01A0001,2911 LOG_SECTOR_INVALID = 0xC01A0001,
4265
4266 /// The log service encountered a log sector with invalid block parity.2912 /// The log service encountered a log sector with invalid block parity.
4267 LOG_SECTOR_PARITY_INVALID = 0xC01A0002,2913 LOG_SECTOR_PARITY_INVALID = 0xC01A0002,
4268
4269 /// The log service encountered a remapped log sector.2914 /// The log service encountered a remapped log sector.
4270 LOG_SECTOR_REMAPPED = 0xC01A0003,2915 LOG_SECTOR_REMAPPED = 0xC01A0003,
4271
4272 /// The log service encountered a partial or incomplete log block.2916 /// The log service encountered a partial or incomplete log block.
4273 LOG_BLOCK_INCOMPLETE = 0xC01A0004,2917 LOG_BLOCK_INCOMPLETE = 0xC01A0004,
4274
4275 /// The log service encountered an attempt to access data outside the active log range.2918 /// The log service encountered an attempt to access data outside the active log range.
4276 LOG_INVALID_RANGE = 0xC01A0005,2919 LOG_INVALID_RANGE = 0xC01A0005,
4277
4278 /// The log service user-log marshaling buffers are exhausted.2920 /// The log service user-log marshaling buffers are exhausted.
4279 LOG_BLOCKS_EXHAUSTED = 0xC01A0006,2921 LOG_BLOCKS_EXHAUSTED = 0xC01A0006,
4280
4281 /// The log service encountered an attempt to read from a marshaling area with an invalid read context.2922 /// The log service encountered an attempt to read from a marshaling area with an invalid read context.
4282 LOG_READ_CONTEXT_INVALID = 0xC01A0007,2923 LOG_READ_CONTEXT_INVALID = 0xC01A0007,
4283
4284 /// The log service encountered an invalid log restart area.2924 /// The log service encountered an invalid log restart area.
4285 LOG_RESTART_INVALID = 0xC01A0008,2925 LOG_RESTART_INVALID = 0xC01A0008,
4286
4287 /// The log service encountered an invalid log block version.2926 /// The log service encountered an invalid log block version.
4288 LOG_BLOCK_VERSION = 0xC01A0009,2927 LOG_BLOCK_VERSION = 0xC01A0009,
4289
4290 /// The log service encountered an invalid log block.2928 /// The log service encountered an invalid log block.
4291 LOG_BLOCK_INVALID = 0xC01A000A,2929 LOG_BLOCK_INVALID = 0xC01A000A,
4292
4293 /// The log service encountered an attempt to read the log with an invalid read mode.2930 /// The log service encountered an attempt to read the log with an invalid read mode.
4294 LOG_READ_MODE_INVALID = 0xC01A000B,2931 LOG_READ_MODE_INVALID = 0xC01A000B,
4295
4296 /// The log service encountered a corrupted metadata file.2932 /// The log service encountered a corrupted metadata file.
4297 LOG_METADATA_CORRUPT = 0xC01A000D,2933 LOG_METADATA_CORRUPT = 0xC01A000D,
4298
4299 /// The log service encountered a metadata file that could not be created by the log file system.2934 /// The log service encountered a metadata file that could not be created by the log file system.
4300 LOG_METADATA_INVALID = 0xC01A000E,2935 LOG_METADATA_INVALID = 0xC01A000E,
4301
4302 /// The log service encountered a metadata file with inconsistent data.2936 /// The log service encountered a metadata file with inconsistent data.
4303 LOG_METADATA_INCONSISTENT = 0xC01A000F,2937 LOG_METADATA_INCONSISTENT = 0xC01A000F,
4304
4305 /// The log service encountered an attempt to erroneously allocate or dispose reservation space.2938 /// The log service encountered an attempt to erroneously allocate or dispose reservation space.
4306 LOG_RESERVATION_INVALID = 0xC01A0010,2939 LOG_RESERVATION_INVALID = 0xC01A0010,
4307
4308 /// The log service cannot delete the log file or the file system container.2940 /// The log service cannot delete the log file or the file system container.
4309 LOG_CANT_DELETE = 0xC01A0011,2941 LOG_CANT_DELETE = 0xC01A0011,
4310
4311 /// The log service has reached the maximum allowable containers allocated to a log file.2942 /// The log service has reached the maximum allowable containers allocated to a log file.
4312 LOG_CONTAINER_LIMIT_EXCEEDED = 0xC01A0012,2943 LOG_CONTAINER_LIMIT_EXCEEDED = 0xC01A0012,
4313
4314 /// The log service has attempted to read or write backward past the start of the log.2944 /// The log service has attempted to read or write backward past the start of the log.
4315 LOG_START_OF_LOG = 0xC01A0013,2945 LOG_START_OF_LOG = 0xC01A0013,
4316
4317 /// The log policy could not be installed because a policy of the same type is already present.2946 /// The log policy could not be installed because a policy of the same type is already present.
4318 LOG_POLICY_ALREADY_INSTALLED = 0xC01A0014,2947 LOG_POLICY_ALREADY_INSTALLED = 0xC01A0014,
4319
4320 /// The log policy in question was not installed at the time of the request.2948 /// The log policy in question was not installed at the time of the request.
4321 LOG_POLICY_NOT_INSTALLED = 0xC01A0015,2949 LOG_POLICY_NOT_INSTALLED = 0xC01A0015,
4322
4323 /// The installed set of policies on the log is invalid.2950 /// The installed set of policies on the log is invalid.
4324 LOG_POLICY_INVALID = 0xC01A0016,2951 LOG_POLICY_INVALID = 0xC01A0016,
4325
4326 /// A policy on the log in question prevented the operation from completing.2952 /// A policy on the log in question prevented the operation from completing.
4327 LOG_POLICY_CONFLICT = 0xC01A0017,2953 LOG_POLICY_CONFLICT = 0xC01A0017,
4328
4329 /// The log space cannot be reclaimed because the log is pinned by the archive tail.2954 /// The log space cannot be reclaimed because the log is pinned by the archive tail.
4330 LOG_PINNED_ARCHIVE_TAIL = 0xC01A0018,2955 LOG_PINNED_ARCHIVE_TAIL = 0xC01A0018,
4331
4332 /// The log record is not a record in the log file.2956 /// The log record is not a record in the log file.
4333 LOG_RECORD_NONEXISTENT = 0xC01A0019,2957 LOG_RECORD_NONEXISTENT = 0xC01A0019,
4334
4335 /// The number of reserved log records or the adjustment of the number of reserved log records is invalid.2958 /// The number of reserved log records or the adjustment of the number of reserved log records is invalid.
4336 LOG_RECORDS_RESERVED_INVALID = 0xC01A001A,2959 LOG_RECORDS_RESERVED_INVALID = 0xC01A001A,
4337
4338 /// The reserved log space or the adjustment of the log space is invalid.2960 /// The reserved log space or the adjustment of the log space is invalid.
4339 LOG_SPACE_RESERVED_INVALID = 0xC01A001B,2961 LOG_SPACE_RESERVED_INVALID = 0xC01A001B,
4340
4341 /// A new or existing archive tail or the base of the active log is invalid.2962 /// A new or existing archive tail or the base of the active log is invalid.
4342 LOG_TAIL_INVALID = 0xC01A001C,2963 LOG_TAIL_INVALID = 0xC01A001C,
4343
4344 /// The log space is exhausted.2964 /// The log space is exhausted.
4345 LOG_FULL = 0xC01A001D,2965 LOG_FULL = 0xC01A001D,
4346
4347 /// The log is multiplexed; no direct writes to the physical log are allowed.2966 /// The log is multiplexed; no direct writes to the physical log are allowed.
4348 LOG_MULTIPLEXED = 0xC01A001E,2967 LOG_MULTIPLEXED = 0xC01A001E,
4349
4350 /// The operation failed because the log is dedicated.2968 /// The operation failed because the log is dedicated.
4351 LOG_DEDICATED = 0xC01A001F,2969 LOG_DEDICATED = 0xC01A001F,
4352
4353 /// The operation requires an archive context.2970 /// The operation requires an archive context.
4354 LOG_ARCHIVE_NOT_IN_PROGRESS = 0xC01A0020,2971 LOG_ARCHIVE_NOT_IN_PROGRESS = 0xC01A0020,
4355
4356 /// Log archival is in progress.2972 /// Log archival is in progress.
4357 LOG_ARCHIVE_IN_PROGRESS = 0xC01A0021,2973 LOG_ARCHIVE_IN_PROGRESS = 0xC01A0021,
4358
4359 /// The operation requires a nonephemeral log, but the log is ephemeral.2974 /// The operation requires a nonephemeral log, but the log is ephemeral.
4360 LOG_EPHEMERAL = 0xC01A0022,2975 LOG_EPHEMERAL = 0xC01A0022,
4361
4362 /// The log must have at least two containers before it can be read from or written to.2976 /// The log must have at least two containers before it can be read from or written to.
4363 LOG_NOT_ENOUGH_CONTAINERS = 0xC01A0023,2977 LOG_NOT_ENOUGH_CONTAINERS = 0xC01A0023,
4364
4365 /// A log client has already registered on the stream.2978 /// A log client has already registered on the stream.
4366 LOG_CLIENT_ALREADY_REGISTERED = 0xC01A0024,2979 LOG_CLIENT_ALREADY_REGISTERED = 0xC01A0024,
4367
4368 /// A log client has not been registered on the stream.2980 /// A log client has not been registered on the stream.
4369 LOG_CLIENT_NOT_REGISTERED = 0xC01A0025,2981 LOG_CLIENT_NOT_REGISTERED = 0xC01A0025,
4370
4371 /// A request has already been made to handle the log full condition.2982 /// A request has already been made to handle the log full condition.
4372 LOG_FULL_HANDLER_IN_PROGRESS = 0xC01A0026,2983 LOG_FULL_HANDLER_IN_PROGRESS = 0xC01A0026,
4373
4374 /// The log service encountered an error when attempting to read from a log container.2984 /// The log service encountered an error when attempting to read from a log container.
4375 LOG_CONTAINER_READ_FAILED = 0xC01A0027,2985 LOG_CONTAINER_READ_FAILED = 0xC01A0027,
4376
4377 /// The log service encountered an error when attempting to write to a log container.2986 /// The log service encountered an error when attempting to write to a log container.
4378 LOG_CONTAINER_WRITE_FAILED = 0xC01A0028,2987 LOG_CONTAINER_WRITE_FAILED = 0xC01A0028,
4379
4380 /// The log service encountered an error when attempting to open a log container.2988 /// The log service encountered an error when attempting to open a log container.
4381 LOG_CONTAINER_OPEN_FAILED = 0xC01A0029,2989 LOG_CONTAINER_OPEN_FAILED = 0xC01A0029,
4382
4383 /// The log service encountered an invalid container state when attempting a requested action.2990 /// The log service encountered an invalid container state when attempting a requested action.
4384 LOG_CONTAINER_STATE_INVALID = 0xC01A002A,2991 LOG_CONTAINER_STATE_INVALID = 0xC01A002A,
4385
4386 /// The log service is not in the correct state to perform a requested action.2992 /// The log service is not in the correct state to perform a requested action.
4387 LOG_STATE_INVALID = 0xC01A002B,2993 LOG_STATE_INVALID = 0xC01A002B,
4388
4389 /// The log space cannot be reclaimed because the log is pinned.2994 /// The log space cannot be reclaimed because the log is pinned.
4390 LOG_PINNED = 0xC01A002C,2995 LOG_PINNED = 0xC01A002C,
4391
4392 /// The log metadata flush failed.2996 /// The log metadata flush failed.
4393 LOG_METADATA_FLUSH_FAILED = 0xC01A002D,2997 LOG_METADATA_FLUSH_FAILED = 0xC01A002D,
4394
4395 /// Security on the log and its containers is inconsistent.2998 /// Security on the log and its containers is inconsistent.
4396 LOG_INCONSISTENT_SECURITY = 0xC01A002E,2999 LOG_INCONSISTENT_SECURITY = 0xC01A002E,
4397
4398 /// Records were appended to the log or reservation changes were made, but the log could not be flushed.3000 /// Records were appended to the log or reservation changes were made, but the log could not be flushed.
4399 LOG_APPENDED_FLUSH_FAILED = 0xC01A002F,3001 LOG_APPENDED_FLUSH_FAILED = 0xC01A002F,
4400
4401 /// The log is pinned due to reservation consuming most of the log space.3002 /// The log is pinned due to reservation consuming most of the log space.
4402 /// Free some reserved records to make space available.3003 /// Free some reserved records to make space available.
4403 LOG_PINNED_RESERVATION = 0xC01A0030,3004 LOG_PINNED_RESERVATION = 0xC01A0030,
4404
4405 /// {Display Driver Stopped Responding} The %hs display driver has stopped working normally.3005 /// {Display Driver Stopped Responding} The %hs display driver has stopped working normally.
4406 /// Save your work and reboot the system to restore full display functionality.3006 /// Save your work and reboot the system to restore full display functionality.
4407 /// The next time you reboot the computer, a dialog box will allow you to upload data about this failure to Microsoft.3007 /// The next time you reboot the computer, a dialog box will allow you to upload data about this failure to Microsoft.
4408 VIDEO_HUNG_DISPLAY_DRIVER_THREAD = 0xC01B00EA,3008 VIDEO_HUNG_DISPLAY_DRIVER_THREAD = 0xC01B00EA,
4409
4410 /// A handler was not defined by the filter for this operation.3009 /// A handler was not defined by the filter for this operation.
4411 FLT_NO_HANDLER_DEFINED = 0xC01C0001,3010 FLT_NO_HANDLER_DEFINED = 0xC01C0001,
4412
4413 /// A context is already defined for this object.3011 /// A context is already defined for this object.
4414 FLT_CONTEXT_ALREADY_DEFINED = 0xC01C0002,3012 FLT_CONTEXT_ALREADY_DEFINED = 0xC01C0002,
4415
4416 /// Asynchronous requests are not valid for this operation.3013 /// Asynchronous requests are not valid for this operation.
4417 FLT_INVALID_ASYNCHRONOUS_REQUEST = 0xC01C0003,3014 FLT_INVALID_ASYNCHRONOUS_REQUEST = 0xC01C0003,
4418
4419 /// This is an internal error code used by the filter manager to determine if a fast I/O operation should be forced down the input/output request packet (IRP) path. Minifilters should never return this value.3015 /// This is an internal error code used by the filter manager to determine if a fast I/O operation should be forced down the input/output request packet (IRP) path. Minifilters should never return this value.
4420 FLT_DISALLOW_FAST_IO = 0xC01C0004,3016 FLT_DISALLOW_FAST_IO = 0xC01C0004,
4421
4422 /// An invalid name request was made.3017 /// An invalid name request was made.
4423 /// The name requested cannot be retrieved at this time.3018 /// The name requested cannot be retrieved at this time.
4424 FLT_INVALID_NAME_REQUEST = 0xC01C0005,3019 FLT_INVALID_NAME_REQUEST = 0xC01C0005,
4425
4426 /// Posting this operation to a worker thread for further processing is not safe at this time because it could lead to a system deadlock.3020 /// Posting this operation to a worker thread for further processing is not safe at this time because it could lead to a system deadlock.
4427 FLT_NOT_SAFE_TO_POST_OPERATION = 0xC01C0006,3021 FLT_NOT_SAFE_TO_POST_OPERATION = 0xC01C0006,
4428
4429 /// The Filter Manager was not initialized when a filter tried to register.3022 /// The Filter Manager was not initialized when a filter tried to register.
4430 /// Make sure that the Filter Manager is loaded as a driver.3023 /// Make sure that the Filter Manager is loaded as a driver.
4431 FLT_NOT_INITIALIZED = 0xC01C0007,3024 FLT_NOT_INITIALIZED = 0xC01C0007,
4432
4433 /// The filter is not ready for attachment to volumes because it has not finished initializing (FltStartFiltering has not been called).3025 /// The filter is not ready for attachment to volumes because it has not finished initializing (FltStartFiltering has not been called).
4434 FLT_FILTER_NOT_READY = 0xC01C0008,3026 FLT_FILTER_NOT_READY = 0xC01C0008,
4435
4436 /// The filter must clean up any operation-specific context at this time because it is being removed from the system before the operation is completed by the lower drivers.3027 /// The filter must clean up any operation-specific context at this time because it is being removed from the system before the operation is completed by the lower drivers.
4437 FLT_POST_OPERATION_CLEANUP = 0xC01C0009,3028 FLT_POST_OPERATION_CLEANUP = 0xC01C0009,
4438
4439 /// The Filter Manager had an internal error from which it cannot recover; therefore, the operation has failed.3029 /// The Filter Manager had an internal error from which it cannot recover; therefore, the operation has failed.
4440 /// This is usually the result of a filter returning an invalid value from a pre-operation callback.3030 /// This is usually the result of a filter returning an invalid value from a pre-operation callback.
4441 FLT_INTERNAL_ERROR = 0xC01C000A,3031 FLT_INTERNAL_ERROR = 0xC01C000A,
4442
4443 /// The object specified for this action is in the process of being deleted; therefore, the action requested cannot be completed at this time.3032 /// The object specified for this action is in the process of being deleted; therefore, the action requested cannot be completed at this time.
4444 FLT_DELETING_OBJECT = 0xC01C000B,3033 FLT_DELETING_OBJECT = 0xC01C000B,
4445
4446 /// A nonpaged pool must be used for this type of context.3034 /// A nonpaged pool must be used for this type of context.
4447 FLT_MUST_BE_NONPAGED_POOL = 0xC01C000C,3035 FLT_MUST_BE_NONPAGED_POOL = 0xC01C000C,
4448
4449 /// A duplicate handler definition has been provided for an operation.3036 /// A duplicate handler definition has been provided for an operation.
4450 FLT_DUPLICATE_ENTRY = 0xC01C000D,3037 FLT_DUPLICATE_ENTRY = 0xC01C000D,
4451
4452 /// The callback data queue has been disabled.3038 /// The callback data queue has been disabled.
4453 FLT_CBDQ_DISABLED = 0xC01C000E,3039 FLT_CBDQ_DISABLED = 0xC01C000E,
4454
4455 /// Do not attach the filter to the volume at this time.3040 /// Do not attach the filter to the volume at this time.
4456 FLT_DO_NOT_ATTACH = 0xC01C000F,3041 FLT_DO_NOT_ATTACH = 0xC01C000F,
4457
4458 /// Do not detach the filter from the volume at this time.3042 /// Do not detach the filter from the volume at this time.
4459 FLT_DO_NOT_DETACH = 0xC01C0010,3043 FLT_DO_NOT_DETACH = 0xC01C0010,
4460
4461 /// An instance already exists at this altitude on the volume specified.3044 /// An instance already exists at this altitude on the volume specified.
4462 FLT_INSTANCE_ALTITUDE_COLLISION = 0xC01C0011,3045 FLT_INSTANCE_ALTITUDE_COLLISION = 0xC01C0011,
4463
4464 /// An instance already exists with this name on the volume specified.3046 /// An instance already exists with this name on the volume specified.
4465 FLT_INSTANCE_NAME_COLLISION = 0xC01C0012,3047 FLT_INSTANCE_NAME_COLLISION = 0xC01C0012,
4466
4467 /// The system could not find the filter specified.3048 /// The system could not find the filter specified.
4468 FLT_FILTER_NOT_FOUND = 0xC01C0013,3049 FLT_FILTER_NOT_FOUND = 0xC01C0013,
4469
4470 /// The system could not find the volume specified.3050 /// The system could not find the volume specified.
4471 FLT_VOLUME_NOT_FOUND = 0xC01C0014,3051 FLT_VOLUME_NOT_FOUND = 0xC01C0014,
4472
4473 /// The system could not find the instance specified.3052 /// The system could not find the instance specified.
4474 FLT_INSTANCE_NOT_FOUND = 0xC01C0015,3053 FLT_INSTANCE_NOT_FOUND = 0xC01C0015,
4475
4476 /// No registered context allocation definition was found for the given request.3054 /// No registered context allocation definition was found for the given request.
4477 FLT_CONTEXT_ALLOCATION_NOT_FOUND = 0xC01C0016,3055 FLT_CONTEXT_ALLOCATION_NOT_FOUND = 0xC01C0016,
4478
4479 /// An invalid parameter was specified during context registration.3056 /// An invalid parameter was specified during context registration.
4480 FLT_INVALID_CONTEXT_REGISTRATION = 0xC01C0017,3057 FLT_INVALID_CONTEXT_REGISTRATION = 0xC01C0017,
4481
4482 /// The name requested was not found in the Filter Manager name cache and could not be retrieved from the file system.3058 /// The name requested was not found in the Filter Manager name cache and could not be retrieved from the file system.
4483 FLT_NAME_CACHE_MISS = 0xC01C0018,3059 FLT_NAME_CACHE_MISS = 0xC01C0018,
4484
4485 /// The requested device object does not exist for the given volume.3060 /// The requested device object does not exist for the given volume.
4486 FLT_NO_DEVICE_OBJECT = 0xC01C0019,3061 FLT_NO_DEVICE_OBJECT = 0xC01C0019,
4487
4488 /// The specified volume is already mounted.3062 /// The specified volume is already mounted.
4489 FLT_VOLUME_ALREADY_MOUNTED = 0xC01C001A,3063 FLT_VOLUME_ALREADY_MOUNTED = 0xC01C001A,
4490
4491 /// The specified transaction context is already enlisted in a transaction.3064 /// The specified transaction context is already enlisted in a transaction.
4492 FLT_ALREADY_ENLISTED = 0xC01C001B,3065 FLT_ALREADY_ENLISTED = 0xC01C001B,
4493
4494 /// The specified context is already attached to another object.3066 /// The specified context is already attached to another object.
4495 FLT_CONTEXT_ALREADY_LINKED = 0xC01C001C,3067 FLT_CONTEXT_ALREADY_LINKED = 0xC01C001C,
4496
4497 /// No waiter is present for the filter's reply to this message.3068 /// No waiter is present for the filter's reply to this message.
4498 FLT_NO_WAITER_FOR_REPLY = 0xC01C0020,3069 FLT_NO_WAITER_FOR_REPLY = 0xC01C0020,
4499
4500 /// A monitor descriptor could not be obtained.3070 /// A monitor descriptor could not be obtained.
4501 MONITOR_NO_DESCRIPTOR = 0xC01D0001,3071 MONITOR_NO_DESCRIPTOR = 0xC01D0001,
4502
4503 /// This release does not support the format of the obtained monitor descriptor.3072 /// This release does not support the format of the obtained monitor descriptor.
4504 MONITOR_UNKNOWN_DESCRIPTOR_FORMAT = 0xC01D0002,3073 MONITOR_UNKNOWN_DESCRIPTOR_FORMAT = 0xC01D0002,
4505
4506 /// The checksum of the obtained monitor descriptor is invalid.3074 /// The checksum of the obtained monitor descriptor is invalid.
4507 MONITOR_INVALID_DESCRIPTOR_CHECKSUM = 0xC01D0003,3075 MONITOR_INVALID_DESCRIPTOR_CHECKSUM = 0xC01D0003,
4508
4509 /// The monitor descriptor contains an invalid standard timing block.3076 /// The monitor descriptor contains an invalid standard timing block.
4510 MONITOR_INVALID_STANDARD_TIMING_BLOCK = 0xC01D0004,3077 MONITOR_INVALID_STANDARD_TIMING_BLOCK = 0xC01D0004,
4511
4512 /// WMI data-block registration failed for one of the MSMonitorClass WMI subclasses.3078 /// WMI data-block registration failed for one of the MSMonitorClass WMI subclasses.
4513 MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED = 0xC01D0005,3079 MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED = 0xC01D0005,
4514
4515 /// The provided monitor descriptor block is either corrupted or does not contain the monitor's detailed serial number.3080 /// The provided monitor descriptor block is either corrupted or does not contain the monitor's detailed serial number.
4516 MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK = 0xC01D0006,3081 MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK = 0xC01D0006,
4517
4518 /// The provided monitor descriptor block is either corrupted or does not contain the monitor's user-friendly name.3082 /// The provided monitor descriptor block is either corrupted or does not contain the monitor's user-friendly name.
4519 MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK = 0xC01D0007,3083 MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK = 0xC01D0007,
4520
4521 /// There is no monitor descriptor data at the specified (offset or size) region.3084 /// There is no monitor descriptor data at the specified (offset or size) region.
4522 MONITOR_NO_MORE_DESCRIPTOR_DATA = 0xC01D0008,3085 MONITOR_NO_MORE_DESCRIPTOR_DATA = 0xC01D0008,
4523
4524 /// The monitor descriptor contains an invalid detailed timing block.3086 /// The monitor descriptor contains an invalid detailed timing block.
4525 MONITOR_INVALID_DETAILED_TIMING_BLOCK = 0xC01D0009,3087 MONITOR_INVALID_DETAILED_TIMING_BLOCK = 0xC01D0009,
4526
4527 /// Monitor descriptor contains invalid manufacture date.3088 /// Monitor descriptor contains invalid manufacture date.
4528 MONITOR_INVALID_MANUFACTURE_DATE = 0xC01D000A,3089 MONITOR_INVALID_MANUFACTURE_DATE = 0xC01D000A,
4529
4530 /// Exclusive mode ownership is needed to create an unmanaged primary allocation.3090 /// Exclusive mode ownership is needed to create an unmanaged primary allocation.
4531 GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER = 0xC01E0000,3091 GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER = 0xC01E0000,
4532
4533 /// The driver needs more DMA buffer space to complete the requested operation.3092 /// The driver needs more DMA buffer space to complete the requested operation.
4534 GRAPHICS_INSUFFICIENT_DMA_BUFFER = 0xC01E0001,3093 GRAPHICS_INSUFFICIENT_DMA_BUFFER = 0xC01E0001,
4535
4536 /// The specified display adapter handle is invalid.3094 /// The specified display adapter handle is invalid.
4537 GRAPHICS_INVALID_DISPLAY_ADAPTER = 0xC01E0002,3095 GRAPHICS_INVALID_DISPLAY_ADAPTER = 0xC01E0002,
4538
4539 /// The specified display adapter and all of its state have been reset.3096 /// The specified display adapter and all of its state have been reset.
4540 GRAPHICS_ADAPTER_WAS_RESET = 0xC01E0003,3097 GRAPHICS_ADAPTER_WAS_RESET = 0xC01E0003,
4541
4542 /// The driver stack does not match the expected driver model.3098 /// The driver stack does not match the expected driver model.
4543 GRAPHICS_INVALID_DRIVER_MODEL = 0xC01E0004,3099 GRAPHICS_INVALID_DRIVER_MODEL = 0xC01E0004,
4544
4545 /// Present happened but ended up into the changed desktop mode.3100 /// Present happened but ended up into the changed desktop mode.
4546 GRAPHICS_PRESENT_MODE_CHANGED = 0xC01E0005,3101 GRAPHICS_PRESENT_MODE_CHANGED = 0xC01E0005,
4547
4548 /// Nothing to present due to desktop occlusion.3102 /// Nothing to present due to desktop occlusion.
4549 GRAPHICS_PRESENT_OCCLUDED = 0xC01E0006,3103 GRAPHICS_PRESENT_OCCLUDED = 0xC01E0006,
4550
4551 /// Not able to present due to denial of desktop access.3104 /// Not able to present due to denial of desktop access.
4552 GRAPHICS_PRESENT_DENIED = 0xC01E0007,3105 GRAPHICS_PRESENT_DENIED = 0xC01E0007,
4553
4554 /// Not able to present with color conversion.3106 /// Not able to present with color conversion.
4555 GRAPHICS_CANNOTCOLORCONVERT = 0xC01E0008,3107 GRAPHICS_CANNOTCOLORCONVERT = 0xC01E0008,
4556
4557 /// Present redirection is disabled (desktop windowing management subsystem is off).3108 /// Present redirection is disabled (desktop windowing management subsystem is off).
4558 GRAPHICS_PRESENT_REDIRECTION_DISABLED = 0xC01E000B,3109 GRAPHICS_PRESENT_REDIRECTION_DISABLED = 0xC01E000B,
4559
4560 /// Previous exclusive VidPn source owner has released its ownership3110 /// Previous exclusive VidPn source owner has released its ownership
4561 GRAPHICS_PRESENT_UNOCCLUDED = 0xC01E000C,3111 GRAPHICS_PRESENT_UNOCCLUDED = 0xC01E000C,
4562
4563 /// Not enough video memory is available to complete the operation.3112 /// Not enough video memory is available to complete the operation.
4564 GRAPHICS_NO_VIDEO_MEMORY = 0xC01E0100,3113 GRAPHICS_NO_VIDEO_MEMORY = 0xC01E0100,
4565
4566 /// Could not probe and lock the underlying memory of an allocation.3114 /// Could not probe and lock the underlying memory of an allocation.
4567 GRAPHICS_CANT_LOCK_MEMORY = 0xC01E0101,3115 GRAPHICS_CANT_LOCK_MEMORY = 0xC01E0101,
4568
4569 /// The allocation is currently busy.3116 /// The allocation is currently busy.
4570 GRAPHICS_ALLOCATION_BUSY = 0xC01E0102,3117 GRAPHICS_ALLOCATION_BUSY = 0xC01E0102,
4571
4572 /// An object being referenced has already reached the maximum reference count and cannot be referenced further.3118 /// An object being referenced has already reached the maximum reference count and cannot be referenced further.
4573 GRAPHICS_TOO_MANY_REFERENCES = 0xC01E0103,3119 GRAPHICS_TOO_MANY_REFERENCES = 0xC01E0103,
4574
4575 /// A problem could not be solved due to an existing condition. Try again later.3120 /// A problem could not be solved due to an existing condition. Try again later.
4576 GRAPHICS_TRY_AGAIN_LATER = 0xC01E0104,3121 GRAPHICS_TRY_AGAIN_LATER = 0xC01E0104,
4577
4578 /// A problem could not be solved due to an existing condition. Try again now.3122 /// A problem could not be solved due to an existing condition. Try again now.
4579 GRAPHICS_TRY_AGAIN_NOW = 0xC01E0105,3123 GRAPHICS_TRY_AGAIN_NOW = 0xC01E0105,
4580
4581 /// The allocation is invalid.3124 /// The allocation is invalid.
4582 GRAPHICS_ALLOCATION_INVALID = 0xC01E0106,3125 GRAPHICS_ALLOCATION_INVALID = 0xC01E0106,
4583
4584 /// No more unswizzling apertures are currently available.3126 /// No more unswizzling apertures are currently available.
4585 GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE = 0xC01E0107,3127 GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE = 0xC01E0107,
4586
4587 /// The current allocation cannot be unswizzled by an aperture.3128 /// The current allocation cannot be unswizzled by an aperture.
4588 GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED = 0xC01E0108,3129 GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED = 0xC01E0108,
4589
4590 /// The request failed because a pinned allocation cannot be evicted.3130 /// The request failed because a pinned allocation cannot be evicted.
4591 GRAPHICS_CANT_EVICT_PINNED_ALLOCATION = 0xC01E0109,3131 GRAPHICS_CANT_EVICT_PINNED_ALLOCATION = 0xC01E0109,
4592
4593 /// The allocation cannot be used from its current segment location for the specified operation.3132 /// The allocation cannot be used from its current segment location for the specified operation.
4594 GRAPHICS_INVALID_ALLOCATION_USAGE = 0xC01E0110,3133 GRAPHICS_INVALID_ALLOCATION_USAGE = 0xC01E0110,
4595
4596 /// A locked allocation cannot be used in the current command buffer.3134 /// A locked allocation cannot be used in the current command buffer.
4597 GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION = 0xC01E0111,3135 GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION = 0xC01E0111,
4598
4599 /// The allocation being referenced has been closed permanently.3136 /// The allocation being referenced has been closed permanently.
4600 GRAPHICS_ALLOCATION_CLOSED = 0xC01E0112,3137 GRAPHICS_ALLOCATION_CLOSED = 0xC01E0112,
4601
4602 /// An invalid allocation instance is being referenced.3138 /// An invalid allocation instance is being referenced.
4603 GRAPHICS_INVALID_ALLOCATION_INSTANCE = 0xC01E0113,3139 GRAPHICS_INVALID_ALLOCATION_INSTANCE = 0xC01E0113,
4604
4605 /// An invalid allocation handle is being referenced.3140 /// An invalid allocation handle is being referenced.
4606 GRAPHICS_INVALID_ALLOCATION_HANDLE = 0xC01E0114,3141 GRAPHICS_INVALID_ALLOCATION_HANDLE = 0xC01E0114,
4607
4608 /// The allocation being referenced does not belong to the current device.3142 /// The allocation being referenced does not belong to the current device.
4609 GRAPHICS_WRONG_ALLOCATION_DEVICE = 0xC01E0115,3143 GRAPHICS_WRONG_ALLOCATION_DEVICE = 0xC01E0115,
4610
4611 /// The specified allocation lost its content.3144 /// The specified allocation lost its content.
4612 GRAPHICS_ALLOCATION_CONTENT_LOST = 0xC01E0116,3145 GRAPHICS_ALLOCATION_CONTENT_LOST = 0xC01E0116,
4613
4614 /// A GPU exception was detected on the given device. The device cannot be scheduled.3146 /// A GPU exception was detected on the given device. The device cannot be scheduled.
4615 GRAPHICS_GPU_EXCEPTION_ON_DEVICE = 0xC01E0200,3147 GRAPHICS_GPU_EXCEPTION_ON_DEVICE = 0xC01E0200,
4616
4617 /// The specified VidPN topology is invalid.3148 /// The specified VidPN topology is invalid.
4618 GRAPHICS_INVALID_VIDPN_TOPOLOGY = 0xC01E0300,3149 GRAPHICS_INVALID_VIDPN_TOPOLOGY = 0xC01E0300,
4619
4620 /// The specified VidPN topology is valid but is not supported by this model of the display adapter.3150 /// The specified VidPN topology is valid but is not supported by this model of the display adapter.
4621 GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED = 0xC01E0301,3151 GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED = 0xC01E0301,
4622
4623 /// The specified VidPN topology is valid but is not currently supported by the display adapter due to allocation of its resources.3152 /// The specified VidPN topology is valid but is not currently supported by the display adapter due to allocation of its resources.
4624 GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED = 0xC01E0302,3153 GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED = 0xC01E0302,
4625
4626 /// The specified VidPN handle is invalid.3154 /// The specified VidPN handle is invalid.
4627 GRAPHICS_INVALID_VIDPN = 0xC01E0303,3155 GRAPHICS_INVALID_VIDPN = 0xC01E0303,
4628
4629 /// The specified video present source is invalid.3156 /// The specified video present source is invalid.
4630 GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE = 0xC01E0304,3157 GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE = 0xC01E0304,
4631
4632 /// The specified video present target is invalid.3158 /// The specified video present target is invalid.
4633 GRAPHICS_INVALID_VIDEO_PRESENT_TARGET = 0xC01E0305,3159 GRAPHICS_INVALID_VIDEO_PRESENT_TARGET = 0xC01E0305,
4634
4635 /// The specified VidPN modality is not supported (for example, at least two of the pinned modes are not co-functional).3160 /// The specified VidPN modality is not supported (for example, at least two of the pinned modes are not co-functional).
4636 GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED = 0xC01E0306,3161 GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED = 0xC01E0306,
4637
4638 /// The specified VidPN source mode set is invalid.3162 /// The specified VidPN source mode set is invalid.
4639 GRAPHICS_INVALID_VIDPN_SOURCEMODESET = 0xC01E0308,3163 GRAPHICS_INVALID_VIDPN_SOURCEMODESET = 0xC01E0308,
4640
4641 /// The specified VidPN target mode set is invalid.3164 /// The specified VidPN target mode set is invalid.
4642 GRAPHICS_INVALID_VIDPN_TARGETMODESET = 0xC01E0309,3165 GRAPHICS_INVALID_VIDPN_TARGETMODESET = 0xC01E0309,
4643
4644 /// The specified video signal frequency is invalid.3166 /// The specified video signal frequency is invalid.
4645 GRAPHICS_INVALID_FREQUENCY = 0xC01E030A,3167 GRAPHICS_INVALID_FREQUENCY = 0xC01E030A,
4646
4647 /// The specified video signal active region is invalid.3168 /// The specified video signal active region is invalid.
4648 GRAPHICS_INVALID_ACTIVE_REGION = 0xC01E030B,3169 GRAPHICS_INVALID_ACTIVE_REGION = 0xC01E030B,
4649
4650 /// The specified video signal total region is invalid.3170 /// The specified video signal total region is invalid.
4651 GRAPHICS_INVALID_TOTAL_REGION = 0xC01E030C,3171 GRAPHICS_INVALID_TOTAL_REGION = 0xC01E030C,
4652
4653 /// The specified video present source mode is invalid.3172 /// The specified video present source mode is invalid.
4654 GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE = 0xC01E0310,3173 GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE = 0xC01E0310,
4655
4656 /// The specified video present target mode is invalid.3174 /// The specified video present target mode is invalid.
4657 GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE = 0xC01E0311,3175 GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE = 0xC01E0311,
4658
4659 /// The pinned mode must remain in the set on the VidPN's co-functional modality enumeration.3176 /// The pinned mode must remain in the set on the VidPN's co-functional modality enumeration.
4660 GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET = 0xC01E0312,3177 GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET = 0xC01E0312,
4661
4662 /// The specified video present path is already in the VidPN's topology.3178 /// The specified video present path is already in the VidPN's topology.
4663 GRAPHICS_PATH_ALREADY_IN_TOPOLOGY = 0xC01E0313,3179 GRAPHICS_PATH_ALREADY_IN_TOPOLOGY = 0xC01E0313,
4664
4665 /// The specified mode is already in the mode set.3180 /// The specified mode is already in the mode set.
4666 GRAPHICS_MODE_ALREADY_IN_MODESET = 0xC01E0314,3181 GRAPHICS_MODE_ALREADY_IN_MODESET = 0xC01E0314,
4667
4668 /// The specified video present source set is invalid.3182 /// The specified video present source set is invalid.
4669 GRAPHICS_INVALID_VIDEOPRESENTSOURCESET = 0xC01E0315,3183 GRAPHICS_INVALID_VIDEOPRESENTSOURCESET = 0xC01E0315,
4670
4671 /// The specified video present target set is invalid.3184 /// The specified video present target set is invalid.
4672 GRAPHICS_INVALID_VIDEOPRESENTTARGETSET = 0xC01E0316,3185 GRAPHICS_INVALID_VIDEOPRESENTTARGETSET = 0xC01E0316,
4673
4674 /// The specified video present source is already in the video present source set.3186 /// The specified video present source is already in the video present source set.
4675 GRAPHICS_SOURCE_ALREADY_IN_SET = 0xC01E0317,3187 GRAPHICS_SOURCE_ALREADY_IN_SET = 0xC01E0317,
4676
4677 /// The specified video present target is already in the video present target set.3188 /// The specified video present target is already in the video present target set.
4678 GRAPHICS_TARGET_ALREADY_IN_SET = 0xC01E0318,3189 GRAPHICS_TARGET_ALREADY_IN_SET = 0xC01E0318,
4679
4680 /// The specified VidPN present path is invalid.3190 /// The specified VidPN present path is invalid.
4681 GRAPHICS_INVALID_VIDPN_PRESENT_PATH = 0xC01E0319,3191 GRAPHICS_INVALID_VIDPN_PRESENT_PATH = 0xC01E0319,
4682
4683 /// The miniport has no recommendation for augmenting the specified VidPN's topology.3192 /// The miniport has no recommendation for augmenting the specified VidPN's topology.
4684 GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY = 0xC01E031A,3193 GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY = 0xC01E031A,
4685
4686 /// The specified monitor frequency range set is invalid.3194 /// The specified monitor frequency range set is invalid.
4687 GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET = 0xC01E031B,3195 GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET = 0xC01E031B,
4688
4689 /// The specified monitor frequency range is invalid.3196 /// The specified monitor frequency range is invalid.
4690 GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE = 0xC01E031C,3197 GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE = 0xC01E031C,
4691
4692 /// The specified frequency range is not in the specified monitor frequency range set.3198 /// The specified frequency range is not in the specified monitor frequency range set.
4693 GRAPHICS_FREQUENCYRANGE_NOT_IN_SET = 0xC01E031D,3199 GRAPHICS_FREQUENCYRANGE_NOT_IN_SET = 0xC01E031D,
4694
4695 /// The specified frequency range is already in the specified monitor frequency range set.3200 /// The specified frequency range is already in the specified monitor frequency range set.
4696 GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET = 0xC01E031F,3201 GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET = 0xC01E031F,
4697
4698 /// The specified mode set is stale. Reacquire the new mode set.3202 /// The specified mode set is stale. Reacquire the new mode set.
4699 GRAPHICS_STALE_MODESET = 0xC01E0320,3203 GRAPHICS_STALE_MODESET = 0xC01E0320,
4700
4701 /// The specified monitor source mode set is invalid.3204 /// The specified monitor source mode set is invalid.
4702 GRAPHICS_INVALID_MONITOR_SOURCEMODESET = 0xC01E0321,3205 GRAPHICS_INVALID_MONITOR_SOURCEMODESET = 0xC01E0321,
4703
4704 /// The specified monitor source mode is invalid.3206 /// The specified monitor source mode is invalid.
4705 GRAPHICS_INVALID_MONITOR_SOURCE_MODE = 0xC01E0322,3207 GRAPHICS_INVALID_MONITOR_SOURCE_MODE = 0xC01E0322,
4706
4707 /// The miniport does not have a recommendation regarding the request to provide a functional VidPN given the current display adapter configuration.3208 /// The miniport does not have a recommendation regarding the request to provide a functional VidPN given the current display adapter configuration.
4708 GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN = 0xC01E0323,3209 GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN = 0xC01E0323,
4709
4710 /// The ID of the specified mode is being used by another mode in the set.3210 /// The ID of the specified mode is being used by another mode in the set.
4711 GRAPHICS_MODE_ID_MUST_BE_UNIQUE = 0xC01E0324,3211 GRAPHICS_MODE_ID_MUST_BE_UNIQUE = 0xC01E0324,
4712
4713 /// The system failed to determine a mode that is supported by both the display adapter and the monitor connected to it.3212 /// The system failed to determine a mode that is supported by both the display adapter and the monitor connected to it.
4714 GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION = 0xC01E0325,3213 GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION = 0xC01E0325,
4715
4716 /// The number of video present targets must be greater than or equal to the number of video present sources.3214 /// The number of video present targets must be greater than or equal to the number of video present sources.
4717 GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES = 0xC01E0326,3215 GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES = 0xC01E0326,
4718
4719 /// The specified present path is not in the VidPN's topology.3216 /// The specified present path is not in the VidPN's topology.
4720 GRAPHICS_PATH_NOT_IN_TOPOLOGY = 0xC01E0327,3217 GRAPHICS_PATH_NOT_IN_TOPOLOGY = 0xC01E0327,
4721
4722 /// The display adapter must have at least one video present source.3218 /// The display adapter must have at least one video present source.
4723 GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE = 0xC01E0328,3219 GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE = 0xC01E0328,
4724
4725 /// The display adapter must have at least one video present target.3220 /// The display adapter must have at least one video present target.
4726 GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET = 0xC01E0329,3221 GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET = 0xC01E0329,
4727
4728 /// The specified monitor descriptor set is invalid.3222 /// The specified monitor descriptor set is invalid.
4729 GRAPHICS_INVALID_MONITORDESCRIPTORSET = 0xC01E032A,3223 GRAPHICS_INVALID_MONITORDESCRIPTORSET = 0xC01E032A,
4730
4731 /// The specified monitor descriptor is invalid.3224 /// The specified monitor descriptor is invalid.
4732 GRAPHICS_INVALID_MONITORDESCRIPTOR = 0xC01E032B,3225 GRAPHICS_INVALID_MONITORDESCRIPTOR = 0xC01E032B,
4733
4734 /// The specified descriptor is not in the specified monitor descriptor set.3226 /// The specified descriptor is not in the specified monitor descriptor set.
4735 GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET = 0xC01E032C,3227 GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET = 0xC01E032C,
4736
4737 /// The specified descriptor is already in the specified monitor descriptor set.3228 /// The specified descriptor is already in the specified monitor descriptor set.
4738 GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET = 0xC01E032D,3229 GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET = 0xC01E032D,
4739
4740 /// The ID of the specified monitor descriptor is being used by another descriptor in the set.3230 /// The ID of the specified monitor descriptor is being used by another descriptor in the set.
4741 GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE = 0xC01E032E,3231 GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE = 0xC01E032E,
4742
4743 /// The specified video present target subset type is invalid.3232 /// The specified video present target subset type is invalid.
4744 GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE = 0xC01E032F,3233 GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE = 0xC01E032F,
4745
4746 /// Two or more of the specified resources are not related to each other, as defined by the interface semantics.3234 /// Two or more of the specified resources are not related to each other, as defined by the interface semantics.
4747 GRAPHICS_RESOURCES_NOT_RELATED = 0xC01E0330,3235 GRAPHICS_RESOURCES_NOT_RELATED = 0xC01E0330,
4748
4749 /// The ID of the specified video present source is being used by another source in the set.3236 /// The ID of the specified video present source is being used by another source in the set.
4750 GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE = 0xC01E0331,3237 GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE = 0xC01E0331,
4751
4752 /// The ID of the specified video present target is being used by another target in the set.3238 /// The ID of the specified video present target is being used by another target in the set.
4753 GRAPHICS_TARGET_ID_MUST_BE_UNIQUE = 0xC01E0332,3239 GRAPHICS_TARGET_ID_MUST_BE_UNIQUE = 0xC01E0332,
4754
4755 /// The specified VidPN source cannot be used because there is no available VidPN target to connect it to.3240 /// The specified VidPN source cannot be used because there is no available VidPN target to connect it to.
4756 GRAPHICS_NO_AVAILABLE_VIDPN_TARGET = 0xC01E0333,3241 GRAPHICS_NO_AVAILABLE_VIDPN_TARGET = 0xC01E0333,
4757
4758 /// The newly arrived monitor could not be associated with a display adapter.3242 /// The newly arrived monitor could not be associated with a display adapter.
4759 GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER = 0xC01E0334,3243 GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER = 0xC01E0334,
4760
4761 /// The particular display adapter does not have an associated VidPN manager.3244 /// The particular display adapter does not have an associated VidPN manager.
4762 GRAPHICS_NO_VIDPNMGR = 0xC01E0335,3245 GRAPHICS_NO_VIDPNMGR = 0xC01E0335,
4763
4764 /// The VidPN manager of the particular display adapter does not have an active VidPN.3246 /// The VidPN manager of the particular display adapter does not have an active VidPN.
4765 GRAPHICS_NO_ACTIVE_VIDPN = 0xC01E0336,3247 GRAPHICS_NO_ACTIVE_VIDPN = 0xC01E0336,
4766
4767 /// The specified VidPN topology is stale; obtain the new topology.3248 /// The specified VidPN topology is stale; obtain the new topology.
4768 GRAPHICS_STALE_VIDPN_TOPOLOGY = 0xC01E0337,3249 GRAPHICS_STALE_VIDPN_TOPOLOGY = 0xC01E0337,
4769
4770 /// No monitor is connected on the specified video present target.3250 /// No monitor is connected on the specified video present target.
4771 GRAPHICS_MONITOR_NOT_CONNECTED = 0xC01E0338,3251 GRAPHICS_MONITOR_NOT_CONNECTED = 0xC01E0338,
4772
4773 /// The specified source is not part of the specified VidPN's topology.3252 /// The specified source is not part of the specified VidPN's topology.
4774 GRAPHICS_SOURCE_NOT_IN_TOPOLOGY = 0xC01E0339,3253 GRAPHICS_SOURCE_NOT_IN_TOPOLOGY = 0xC01E0339,
4775
4776 /// The specified primary surface size is invalid.3254 /// The specified primary surface size is invalid.
4777 GRAPHICS_INVALID_PRIMARYSURFACE_SIZE = 0xC01E033A,3255 GRAPHICS_INVALID_PRIMARYSURFACE_SIZE = 0xC01E033A,
4778
4779 /// The specified visible region size is invalid.3256 /// The specified visible region size is invalid.
4780 GRAPHICS_INVALID_VISIBLEREGION_SIZE = 0xC01E033B,3257 GRAPHICS_INVALID_VISIBLEREGION_SIZE = 0xC01E033B,
4781
4782 /// The specified stride is invalid.3258 /// The specified stride is invalid.
4783 GRAPHICS_INVALID_STRIDE = 0xC01E033C,3259 GRAPHICS_INVALID_STRIDE = 0xC01E033C,
4784
4785 /// The specified pixel format is invalid.3260 /// The specified pixel format is invalid.
4786 GRAPHICS_INVALID_PIXELFORMAT = 0xC01E033D,3261 GRAPHICS_INVALID_PIXELFORMAT = 0xC01E033D,
4787
4788 /// The specified color basis is invalid.3262 /// The specified color basis is invalid.
4789 GRAPHICS_INVALID_COLORBASIS = 0xC01E033E,3263 GRAPHICS_INVALID_COLORBASIS = 0xC01E033E,
4790
4791 /// The specified pixel value access mode is invalid.3264 /// The specified pixel value access mode is invalid.
4792 GRAPHICS_INVALID_PIXELVALUEACCESSMODE = 0xC01E033F,3265 GRAPHICS_INVALID_PIXELVALUEACCESSMODE = 0xC01E033F,
4793
4794 /// The specified target is not part of the specified VidPN's topology.3266 /// The specified target is not part of the specified VidPN's topology.
4795 GRAPHICS_TARGET_NOT_IN_TOPOLOGY = 0xC01E0340,3267 GRAPHICS_TARGET_NOT_IN_TOPOLOGY = 0xC01E0340,
4796
4797 /// Failed to acquire the display mode management interface.3268 /// Failed to acquire the display mode management interface.
4798 GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT = 0xC01E0341,3269 GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT = 0xC01E0341,
4799
4800 /// The specified VidPN source is already owned by a DMM client and cannot be used until that client releases it.3270 /// The specified VidPN source is already owned by a DMM client and cannot be used until that client releases it.
4801 GRAPHICS_VIDPN_SOURCE_IN_USE = 0xC01E0342,3271 GRAPHICS_VIDPN_SOURCE_IN_USE = 0xC01E0342,
4802
4803 /// The specified VidPN is active and cannot be accessed.3272 /// The specified VidPN is active and cannot be accessed.
4804 GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN = 0xC01E0343,3273 GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN = 0xC01E0343,
4805
4806 /// The specified VidPN's present path importance ordinal is invalid.3274 /// The specified VidPN's present path importance ordinal is invalid.
4807 GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL = 0xC01E0344,3275 GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL = 0xC01E0344,
4808
4809 /// The specified VidPN's present path content geometry transformation is invalid.3276 /// The specified VidPN's present path content geometry transformation is invalid.
4810 GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION = 0xC01E0345,3277 GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION = 0xC01E0345,
4811
4812 /// The specified content geometry transformation is not supported on the respective VidPN present path.3278 /// The specified content geometry transformation is not supported on the respective VidPN present path.
4813 GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED = 0xC01E0346,3279 GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED = 0xC01E0346,
4814
4815 /// The specified gamma ramp is invalid.3280 /// The specified gamma ramp is invalid.
4816 GRAPHICS_INVALID_GAMMA_RAMP = 0xC01E0347,3281 GRAPHICS_INVALID_GAMMA_RAMP = 0xC01E0347,
4817
4818 /// The specified gamma ramp is not supported on the respective VidPN present path.3282 /// The specified gamma ramp is not supported on the respective VidPN present path.
4819 GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED = 0xC01E0348,3283 GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED = 0xC01E0348,
4820
4821 /// Multisampling is not supported on the respective VidPN present path.3284 /// Multisampling is not supported on the respective VidPN present path.
4822 GRAPHICS_MULTISAMPLING_NOT_SUPPORTED = 0xC01E0349,3285 GRAPHICS_MULTISAMPLING_NOT_SUPPORTED = 0xC01E0349,
4823
4824 /// The specified mode is not in the specified mode set.3286 /// The specified mode is not in the specified mode set.
4825 GRAPHICS_MODE_NOT_IN_MODESET = 0xC01E034A,3287 GRAPHICS_MODE_NOT_IN_MODESET = 0xC01E034A,
4826
4827 /// The specified VidPN topology recommendation reason is invalid.3288 /// The specified VidPN topology recommendation reason is invalid.
4828 GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON = 0xC01E034D,3289 GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON = 0xC01E034D,
4829
4830 /// The specified VidPN present path content type is invalid.3290 /// The specified VidPN present path content type is invalid.
4831 GRAPHICS_INVALID_PATH_CONTENT_TYPE = 0xC01E034E,3291 GRAPHICS_INVALID_PATH_CONTENT_TYPE = 0xC01E034E,
4832
4833 /// The specified VidPN present path copy protection type is invalid.3292 /// The specified VidPN present path copy protection type is invalid.
4834 GRAPHICS_INVALID_COPYPROTECTION_TYPE = 0xC01E034F,3293 GRAPHICS_INVALID_COPYPROTECTION_TYPE = 0xC01E034F,
4835
4836 /// Only one unassigned mode set can exist at any one time for a particular VidPN source or target.3294 /// Only one unassigned mode set can exist at any one time for a particular VidPN source or target.
4837 GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS = 0xC01E0350,3295 GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS = 0xC01E0350,
4838
4839 /// The specified scan line ordering type is invalid.3296 /// The specified scan line ordering type is invalid.
4840 GRAPHICS_INVALID_SCANLINE_ORDERING = 0xC01E0352,3297 GRAPHICS_INVALID_SCANLINE_ORDERING = 0xC01E0352,
4841
4842 /// The topology changes are not allowed for the specified VidPN.3298 /// The topology changes are not allowed for the specified VidPN.
4843 GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED = 0xC01E0353,3299 GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED = 0xC01E0353,
4844
4845 /// All available importance ordinals are being used in the specified topology.3300 /// All available importance ordinals are being used in the specified topology.
4846 GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS = 0xC01E0354,3301 GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS = 0xC01E0354,
4847
4848 /// The specified primary surface has a different private-format attribute than the current primary surface.3302 /// The specified primary surface has a different private-format attribute than the current primary surface.
4849 GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT = 0xC01E0355,3303 GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT = 0xC01E0355,
4850
4851 /// The specified mode-pruning algorithm is invalid.3304 /// The specified mode-pruning algorithm is invalid.
4852 GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM = 0xC01E0356,3305 GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM = 0xC01E0356,
4853
4854 /// The specified monitor-capability origin is invalid.3306 /// The specified monitor-capability origin is invalid.
4855 GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN = 0xC01E0357,3307 GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN = 0xC01E0357,
4856
4857 /// The specified monitor-frequency range constraint is invalid.3308 /// The specified monitor-frequency range constraint is invalid.
4858 GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT = 0xC01E0358,3309 GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT = 0xC01E0358,
4859
4860 /// The maximum supported number of present paths has been reached.3310 /// The maximum supported number of present paths has been reached.
4861 GRAPHICS_MAX_NUM_PATHS_REACHED = 0xC01E0359,3311 GRAPHICS_MAX_NUM_PATHS_REACHED = 0xC01E0359,
4862
4863 /// The miniport requested that augmentation be canceled for the specified source of the specified VidPN's topology.3312 /// The miniport requested that augmentation be canceled for the specified source of the specified VidPN's topology.
4864 GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION = 0xC01E035A,3313 GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION = 0xC01E035A,
4865
4866 /// The specified client type was not recognized.3314 /// The specified client type was not recognized.
4867 GRAPHICS_INVALID_CLIENT_TYPE = 0xC01E035B,3315 GRAPHICS_INVALID_CLIENT_TYPE = 0xC01E035B,
4868
4869 /// The client VidPN is not set on this adapter (for example, no user mode-initiated mode changes have taken place on this adapter).3316 /// The client VidPN is not set on this adapter (for example, no user mode-initiated mode changes have taken place on this adapter).
4870 GRAPHICS_CLIENTVIDPN_NOT_SET = 0xC01E035C,3317 GRAPHICS_CLIENTVIDPN_NOT_SET = 0xC01E035C,
4871
4872 /// The specified display adapter child device already has an external device connected to it.3318 /// The specified display adapter child device already has an external device connected to it.
4873 GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED = 0xC01E0400,3319 GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED = 0xC01E0400,
4874
4875 /// The display adapter child device does not support reporting a descriptor.3320 /// The display adapter child device does not support reporting a descriptor.
4876 GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED = 0xC01E0401,3321 GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED = 0xC01E0401,
4877
4878 /// The display adapter is not linked to any other adapters.3322 /// The display adapter is not linked to any other adapters.
4879 GRAPHICS_NOT_A_LINKED_ADAPTER = 0xC01E0430,3323 GRAPHICS_NOT_A_LINKED_ADAPTER = 0xC01E0430,
4880
4881 /// The lead adapter in a linked configuration was not enumerated yet.3324 /// The lead adapter in a linked configuration was not enumerated yet.
4882 GRAPHICS_LEADLINK_NOT_ENUMERATED = 0xC01E0431,3325 GRAPHICS_LEADLINK_NOT_ENUMERATED = 0xC01E0431,
4883
4884 /// Some chain adapters in a linked configuration have not yet been enumerated.3326 /// Some chain adapters in a linked configuration have not yet been enumerated.
4885 GRAPHICS_CHAINLINKS_NOT_ENUMERATED = 0xC01E0432,3327 GRAPHICS_CHAINLINKS_NOT_ENUMERATED = 0xC01E0432,
4886
4887 /// The chain of linked adapters is not ready to start because of an unknown failure.3328 /// The chain of linked adapters is not ready to start because of an unknown failure.
4888 GRAPHICS_ADAPTER_CHAIN_NOT_READY = 0xC01E0433,3329 GRAPHICS_ADAPTER_CHAIN_NOT_READY = 0xC01E0433,
4889
4890 /// An attempt was made to start a lead link display adapter when the chain links had not yet started.3330 /// An attempt was made to start a lead link display adapter when the chain links had not yet started.
4891 GRAPHICS_CHAINLINKS_NOT_STARTED = 0xC01E0434,3331 GRAPHICS_CHAINLINKS_NOT_STARTED = 0xC01E0434,
4892
4893 /// An attempt was made to turn on a lead link display adapter when the chain links were turned off.3332 /// An attempt was made to turn on a lead link display adapter when the chain links were turned off.
4894 GRAPHICS_CHAINLINKS_NOT_POWERED_ON = 0xC01E0435,3333 GRAPHICS_CHAINLINKS_NOT_POWERED_ON = 0xC01E0435,
4895
4896 /// The adapter link was found in an inconsistent state.3334 /// The adapter link was found in an inconsistent state.
4897 /// Not all adapters are in an expected PNP/power state.3335 /// Not all adapters are in an expected PNP/power state.
4898 GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE = 0xC01E0436,3336 GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE = 0xC01E0436,
4899
4900 /// The driver trying to start is not the same as the driver for the posted display adapter.3337 /// The driver trying to start is not the same as the driver for the posted display adapter.
4901 GRAPHICS_NOT_POST_DEVICE_DRIVER = 0xC01E0438,3338 GRAPHICS_NOT_POST_DEVICE_DRIVER = 0xC01E0438,
4902
4903 /// An operation is being attempted that requires the display adapter to be in a quiescent state.3339 /// An operation is being attempted that requires the display adapter to be in a quiescent state.
4904 GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED = 0xC01E043B,3340 GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED = 0xC01E043B,
4905
4906 /// The driver does not support OPM.3341 /// The driver does not support OPM.
4907 GRAPHICS_OPM_NOT_SUPPORTED = 0xC01E0500,3342 GRAPHICS_OPM_NOT_SUPPORTED = 0xC01E0500,
4908
4909 /// The driver does not support COPP.3343 /// The driver does not support COPP.
4910 GRAPHICS_COPP_NOT_SUPPORTED = 0xC01E0501,3344 GRAPHICS_COPP_NOT_SUPPORTED = 0xC01E0501,
4911
4912 /// The driver does not support UAB.3345 /// The driver does not support UAB.
4913 GRAPHICS_UAB_NOT_SUPPORTED = 0xC01E0502,3346 GRAPHICS_UAB_NOT_SUPPORTED = 0xC01E0502,
4914
4915 /// The specified encrypted parameters are invalid.3347 /// The specified encrypted parameters are invalid.
4916 GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS = 0xC01E0503,3348 GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS = 0xC01E0503,
4917
4918 /// An array passed to a function cannot hold all of the data that the function wants to put in it.3349 /// An array passed to a function cannot hold all of the data that the function wants to put in it.
4919 GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL = 0xC01E0504,3350 GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL = 0xC01E0504,
4920
4921 /// The GDI display device passed to this function does not have any active protected outputs.3351 /// The GDI display device passed to this function does not have any active protected outputs.
4922 GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST = 0xC01E0505,3352 GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST = 0xC01E0505,
4923
4924 /// The PVP cannot find an actual GDI display device that corresponds to the passed-in GDI display device name.3353 /// The PVP cannot find an actual GDI display device that corresponds to the passed-in GDI display device name.
4925 GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME = 0xC01E0506,3354 GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME = 0xC01E0506,
4926
4927 /// This function failed because the GDI display device passed to it was not attached to the Windows desktop.3355 /// This function failed because the GDI display device passed to it was not attached to the Windows desktop.
4928 GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP = 0xC01E0507,3356 GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP = 0xC01E0507,
4929
4930 /// The PVP does not support mirroring display devices because they do not have any protected outputs.3357 /// The PVP does not support mirroring display devices because they do not have any protected outputs.
4931 GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED = 0xC01E0508,3358 GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED = 0xC01E0508,
4932
4933 /// The function failed because an invalid pointer parameter was passed to it.3359 /// The function failed because an invalid pointer parameter was passed to it.
4934 /// A pointer parameter is invalid if it is null, is not correctly aligned, or it points to an invalid address or a kernel mode address.3360 /// A pointer parameter is invalid if it is null, is not correctly aligned, or it points to an invalid address or a kernel mode address.
4935 GRAPHICS_OPM_INVALID_POINTER = 0xC01E050A,3361 GRAPHICS_OPM_INVALID_POINTER = 0xC01E050A,
4936
4937 /// An internal error caused an operation to fail.3362 /// An internal error caused an operation to fail.
4938 GRAPHICS_OPM_INTERNAL_ERROR = 0xC01E050B,3363 GRAPHICS_OPM_INTERNAL_ERROR = 0xC01E050B,
4939
4940 /// The function failed because the caller passed in an invalid OPM user-mode handle.3364 /// The function failed because the caller passed in an invalid OPM user-mode handle.
4941 GRAPHICS_OPM_INVALID_HANDLE = 0xC01E050C,3365 GRAPHICS_OPM_INVALID_HANDLE = 0xC01E050C,
4942
4943 /// This function failed because the GDI device passed to it did not have any monitors associated with it.3366 /// This function failed because the GDI device passed to it did not have any monitors associated with it.
4944 GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE = 0xC01E050D,3367 GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE = 0xC01E050D,
4945
4946 /// A certificate could not be returned because the certificate buffer passed to the function was too small.3368 /// A certificate could not be returned because the certificate buffer passed to the function was too small.
4947 GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH = 0xC01E050E,3369 GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH = 0xC01E050E,
4948
4949 /// DxgkDdiOpmCreateProtectedOutput() could not create a protected output because the video present yarget is in spanning mode.3370 /// DxgkDdiOpmCreateProtectedOutput() could not create a protected output because the video present yarget is in spanning mode.
4950 GRAPHICS_OPM_SPANNING_MODE_ENABLED = 0xC01E050F,3371 GRAPHICS_OPM_SPANNING_MODE_ENABLED = 0xC01E050F,
4951
4952 /// DxgkDdiOpmCreateProtectedOutput() could not create a protected output because the video present target is in theater mode.3372 /// DxgkDdiOpmCreateProtectedOutput() could not create a protected output because the video present target is in theater mode.
4953 GRAPHICS_OPM_THEATER_MODE_ENABLED = 0xC01E0510,3373 GRAPHICS_OPM_THEATER_MODE_ENABLED = 0xC01E0510,
4954
4955 /// The function call failed because the display adapter's hardware functionality scan (HFS) failed to validate the graphics hardware.3374 /// The function call failed because the display adapter's hardware functionality scan (HFS) failed to validate the graphics hardware.
4956 GRAPHICS_PVP_HFS_FAILED = 0xC01E0511,3375 GRAPHICS_PVP_HFS_FAILED = 0xC01E0511,
4957
4958 /// The HDCP SRM passed to this function did not comply with section 5 of the HDCP 1.1 specification.3376 /// The HDCP SRM passed to this function did not comply with section 5 of the HDCP 1.1 specification.
4959 GRAPHICS_OPM_INVALID_SRM = 0xC01E0512,3377 GRAPHICS_OPM_INVALID_SRM = 0xC01E0512,
4960
4961 /// The protected output cannot enable the HDCP system because it does not support it.3378 /// The protected output cannot enable the HDCP system because it does not support it.
4962 GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP = 0xC01E0513,3379 GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP = 0xC01E0513,
4963
4964 /// The protected output cannot enable analog copy protection because it does not support it.3380 /// The protected output cannot enable analog copy protection because it does not support it.
4965 GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP = 0xC01E0514,3381 GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP = 0xC01E0514,
4966
4967 /// The protected output cannot enable the CGMS-A protection technology because it does not support it.3382 /// The protected output cannot enable the CGMS-A protection technology because it does not support it.
4968 GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA = 0xC01E0515,3383 GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA = 0xC01E0515,
4969
4970 /// DxgkDdiOPMGetInformation() cannot return the version of the SRM being used because the application never successfully passed an SRM to the protected output.3384 /// DxgkDdiOPMGetInformation() cannot return the version of the SRM being used because the application never successfully passed an SRM to the protected output.
4971 GRAPHICS_OPM_HDCP_SRM_NEVER_SET = 0xC01E0516,3385 GRAPHICS_OPM_HDCP_SRM_NEVER_SET = 0xC01E0516,
4972
4973 /// DxgkDdiOPMConfigureProtectedOutput() cannot enable the specified output protection technology because the output's screen resolution is too high.3386 /// DxgkDdiOPMConfigureProtectedOutput() cannot enable the specified output protection technology because the output's screen resolution is too high.
4974 GRAPHICS_OPM_RESOLUTION_TOO_HIGH = 0xC01E0517,3387 GRAPHICS_OPM_RESOLUTION_TOO_HIGH = 0xC01E0517,
4975
4976 /// DxgkDdiOPMConfigureProtectedOutput() cannot enable HDCP because other physical outputs are using the display adapter's HDCP hardware.3388 /// DxgkDdiOPMConfigureProtectedOutput() cannot enable HDCP because other physical outputs are using the display adapter's HDCP hardware.
4977 GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE = 0xC01E0518,3389 GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE = 0xC01E0518,
4978
4979 /// The operating system asynchronously destroyed this OPM-protected output because the operating system state changed.3390 /// The operating system asynchronously destroyed this OPM-protected output because the operating system state changed.
4980 /// This error typically occurs because the monitor PDO associated with this protected output was removed or stopped, the protected output's session became a nonconsole session, or the protected output's desktop became inactive.3391 /// This error typically occurs because the monitor PDO associated with this protected output was removed or stopped, the protected output's session became a nonconsole session, or the protected output's desktop became inactive.
4981 GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS = 0xC01E051A,3392 GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS = 0xC01E051A,
4982
4983 /// OPM functions cannot be called when a session is changing its type.3393 /// OPM functions cannot be called when a session is changing its type.
4984 /// Three types of sessions currently exist: console, disconnected, and remote (RDP or ICA).3394 /// Three types of sessions currently exist: console, disconnected, and remote (RDP or ICA).
4985 GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS = 0xC01E051B,3395 GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS = 0xC01E051B,
4986
4987 /// The DxgkDdiOPMGetCOPPCompatibleInformation, DxgkDdiOPMGetInformation, or DxgkDdiOPMConfigureProtectedOutput function failed.3396 /// The DxgkDdiOPMGetCOPPCompatibleInformation, DxgkDdiOPMGetInformation, or DxgkDdiOPMConfigureProtectedOutput function failed.
4988 /// This error is returned only if a protected output has OPM semantics.3397 /// This error is returned only if a protected output has OPM semantics.
4989 /// DxgkDdiOPMGetCOPPCompatibleInformation always returns this error if a protected output has OPM semantics.3398 /// DxgkDdiOPMGetCOPPCompatibleInformation always returns this error if a protected output has OPM semantics.
4990 /// DxgkDdiOPMGetInformation returns this error code if the caller requested COPP-specific information.3399 /// DxgkDdiOPMGetInformation returns this error code if the caller requested COPP-specific information.
4991 /// DxgkDdiOPMConfigureProtectedOutput returns this error when the caller tries to use a COPP-specific command.3400 /// DxgkDdiOPMConfigureProtectedOutput returns this error when the caller tries to use a COPP-specific command.
4992 GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS = 0xC01E051C,3401 GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS = 0xC01E051C,
4993
4994 /// The DxgkDdiOPMGetInformation and DxgkDdiOPMGetCOPPCompatibleInformation functions return this error code if the passed-in sequence number is not the expected sequence number or the passed-in OMAC value is invalid.3402 /// The DxgkDdiOPMGetInformation and DxgkDdiOPMGetCOPPCompatibleInformation functions return this error code if the passed-in sequence number is not the expected sequence number or the passed-in OMAC value is invalid.
4995 GRAPHICS_OPM_INVALID_INFORMATION_REQUEST = 0xC01E051D,3403 GRAPHICS_OPM_INVALID_INFORMATION_REQUEST = 0xC01E051D,
4996
4997 /// The function failed because an unexpected error occurred inside a display driver.3404 /// The function failed because an unexpected error occurred inside a display driver.
4998 GRAPHICS_OPM_DRIVER_INTERNAL_ERROR = 0xC01E051E,3405 GRAPHICS_OPM_DRIVER_INTERNAL_ERROR = 0xC01E051E,
4999
5000 /// The DxgkDdiOPMGetCOPPCompatibleInformation, DxgkDdiOPMGetInformation, or DxgkDdiOPMConfigureProtectedOutput function failed.3406 /// The DxgkDdiOPMGetCOPPCompatibleInformation, DxgkDdiOPMGetInformation, or DxgkDdiOPMConfigureProtectedOutput function failed.
5001 /// This error is returned only if a protected output has COPP semantics.3407 /// This error is returned only if a protected output has COPP semantics.
5002 /// DxgkDdiOPMGetCOPPCompatibleInformation returns this error code if the caller requested OPM-specific information.3408 /// DxgkDdiOPMGetCOPPCompatibleInformation returns this error code if the caller requested OPM-specific information.
5003 /// DxgkDdiOPMGetInformation always returns this error if a protected output has COPP semantics.3409 /// DxgkDdiOPMGetInformation always returns this error if a protected output has COPP semantics.
5004 /// DxgkDdiOPMConfigureProtectedOutput returns this error when the caller tries to use an OPM-specific command.3410 /// DxgkDdiOPMConfigureProtectedOutput returns this error when the caller tries to use an OPM-specific command.
5005 GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS = 0xC01E051F,3411 GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS = 0xC01E051F,
5006
5007 /// The DxgkDdiOPMGetCOPPCompatibleInformation and DxgkDdiOPMConfigureProtectedOutput functions return this error if the display driver does not support the DXGKMDT_OPM_GET_ACP_AND_CGMSA_SIGNALING and DXGKMDT_OPM_SET_ACP_AND_CGMSA_SIGNALING GUIDs.3412 /// The DxgkDdiOPMGetCOPPCompatibleInformation and DxgkDdiOPMConfigureProtectedOutput functions return this error if the display driver does not support the DXGKMDT_OPM_GET_ACP_AND_CGMSA_SIGNALING and DXGKMDT_OPM_SET_ACP_AND_CGMSA_SIGNALING GUIDs.
5008 GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED = 0xC01E0520,3413 GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED = 0xC01E0520,
5009
5010 /// The DxgkDdiOPMConfigureProtectedOutput function returns this error code if the passed-in sequence number is not the expected sequence number or the passed-in OMAC value is invalid.3414 /// The DxgkDdiOPMConfigureProtectedOutput function returns this error code if the passed-in sequence number is not the expected sequence number or the passed-in OMAC value is invalid.
5011 GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST = 0xC01E0521,3415 GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST = 0xC01E0521,
5012
5013 /// The monitor connected to the specified video output does not have an I2C bus.3416 /// The monitor connected to the specified video output does not have an I2C bus.
5014 GRAPHICS_I2C_NOT_SUPPORTED = 0xC01E0580,3417 GRAPHICS_I2C_NOT_SUPPORTED = 0xC01E0580,
5015
5016 /// No device on the I2C bus has the specified address.3418 /// No device on the I2C bus has the specified address.
5017 GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST = 0xC01E0581,3419 GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST = 0xC01E0581,
5018
5019 /// An error occurred while transmitting data to the device on the I2C bus.3420 /// An error occurred while transmitting data to the device on the I2C bus.
5020 GRAPHICS_I2C_ERROR_TRANSMITTING_DATA = 0xC01E0582,3421 GRAPHICS_I2C_ERROR_TRANSMITTING_DATA = 0xC01E0582,
5021
5022 /// An error occurred while receiving data from the device on the I2C bus.3422 /// An error occurred while receiving data from the device on the I2C bus.
5023 GRAPHICS_I2C_ERROR_RECEIVING_DATA = 0xC01E0583,3423 GRAPHICS_I2C_ERROR_RECEIVING_DATA = 0xC01E0583,
5024
5025 /// The monitor does not support the specified VCP code.3424 /// The monitor does not support the specified VCP code.
5026 GRAPHICS_DDCCI_VCP_NOT_SUPPORTED = 0xC01E0584,3425 GRAPHICS_DDCCI_VCP_NOT_SUPPORTED = 0xC01E0584,
5027
5028 /// The data received from the monitor is invalid.3426 /// The data received from the monitor is invalid.
5029 GRAPHICS_DDCCI_INVALID_DATA = 0xC01E0585,3427 GRAPHICS_DDCCI_INVALID_DATA = 0xC01E0585,
5030
5031 /// A function call failed because a monitor returned an invalid timing status byte when the operating system used the DDC/CI get timing report and timing message command to get a timing report from a monitor.3428 /// A function call failed because a monitor returned an invalid timing status byte when the operating system used the DDC/CI get timing report and timing message command to get a timing report from a monitor.
5032 GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE = 0xC01E0586,3429 GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE = 0xC01E0586,
5033
5034 /// A monitor returned a DDC/CI capabilities string that did not comply with the ACCESS.bus 3.0, DDC/CI 1.1, or MCCS 2 Revision 1 specification.3430 /// A monitor returned a DDC/CI capabilities string that did not comply with the ACCESS.bus 3.0, DDC/CI 1.1, or MCCS 2 Revision 1 specification.
5035 GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING = 0xC01E0587,3431 GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING = 0xC01E0587,
5036
5037 /// An internal error caused an operation to fail.3432 /// An internal error caused an operation to fail.
5038 GRAPHICS_MCA_INTERNAL_ERROR = 0xC01E0588,3433 GRAPHICS_MCA_INTERNAL_ERROR = 0xC01E0588,
5039
5040 /// An operation failed because a DDC/CI message had an invalid value in its command field.3434 /// An operation failed because a DDC/CI message had an invalid value in its command field.
5041 GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND = 0xC01E0589,3435 GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND = 0xC01E0589,
5042
5043 /// This error occurred because a DDC/CI message had an invalid value in its length field.3436 /// This error occurred because a DDC/CI message had an invalid value in its length field.
5044 GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH = 0xC01E058A,3437 GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH = 0xC01E058A,
5045
5046 /// This error occurred because the value in a DDC/CI message's checksum field did not match the message's computed checksum value.3438 /// This error occurred because the value in a DDC/CI message's checksum field did not match the message's computed checksum value.
5047 /// This error implies that the data was corrupted while it was being transmitted from a monitor to a computer.3439 /// This error implies that the data was corrupted while it was being transmitted from a monitor to a computer.
5048 GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM = 0xC01E058B,3440 GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM = 0xC01E058B,
5049
5050 /// This function failed because an invalid monitor handle was passed to it.3441 /// This function failed because an invalid monitor handle was passed to it.
5051 GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE = 0xC01E058C,3442 GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE = 0xC01E058C,
5052
5053 /// The operating system asynchronously destroyed the monitor that corresponds to this handle because the operating system's state changed.3443 /// The operating system asynchronously destroyed the monitor that corresponds to this handle because the operating system's state changed.
5054 /// This error typically occurs because the monitor PDO associated with this handle was removed or stopped, or a display mode change occurred.3444 /// This error typically occurs because the monitor PDO associated with this handle was removed or stopped, or a display mode change occurred.
5055 /// A display mode change occurs when Windows sends a WM_DISPLAYCHANGE message to applications.3445 /// A display mode change occurs when Windows sends a WM_DISPLAYCHANGE message to applications.
5056 GRAPHICS_MONITOR_NO_LONGER_EXISTS = 0xC01E058D,3446 GRAPHICS_MONITOR_NO_LONGER_EXISTS = 0xC01E058D,
5057
5058 /// This function can be used only if a program is running in the local console session.3447 /// This function can be used only if a program is running in the local console session.
5059 /// It cannot be used if a program is running on a remote desktop session or on a terminal server session.3448 /// It cannot be used if a program is running on a remote desktop session or on a terminal server session.
5060 GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED = 0xC01E05E0,3449 GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED = 0xC01E05E0,
5061
5062 /// This function cannot find an actual GDI display device that corresponds to the specified GDI display device name.3450 /// This function cannot find an actual GDI display device that corresponds to the specified GDI display device name.
5063 GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME = 0xC01E05E1,3451 GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME = 0xC01E05E1,
5064
5065 /// The function failed because the specified GDI display device was not attached to the Windows desktop.3452 /// The function failed because the specified GDI display device was not attached to the Windows desktop.
5066 GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP = 0xC01E05E2,3453 GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP = 0xC01E05E2,
5067
5068 /// This function does not support GDI mirroring display devices because GDI mirroring display devices do not have any physical monitors associated with them.3454 /// This function does not support GDI mirroring display devices because GDI mirroring display devices do not have any physical monitors associated with them.
5069 GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED = 0xC01E05E3,3455 GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED = 0xC01E05E3,
5070
5071 /// The function failed because an invalid pointer parameter was passed to it.3456 /// The function failed because an invalid pointer parameter was passed to it.
5072 /// A pointer parameter is invalid if it is null, is not correctly aligned, or points to an invalid address or to a kernel mode address.3457 /// A pointer parameter is invalid if it is null, is not correctly aligned, or points to an invalid address or to a kernel mode address.
5073 GRAPHICS_INVALID_POINTER = 0xC01E05E4,3458 GRAPHICS_INVALID_POINTER = 0xC01E05E4,
5074
5075 /// This function failed because the GDI device passed to it did not have a monitor associated with it.3459 /// This function failed because the GDI device passed to it did not have a monitor associated with it.
5076 GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE = 0xC01E05E5,3460 GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE = 0xC01E05E5,
5077
5078 /// An array passed to the function cannot hold all of the data that the function must copy into the array.3461 /// An array passed to the function cannot hold all of the data that the function must copy into the array.
5079 GRAPHICS_PARAMETER_ARRAY_TOO_SMALL = 0xC01E05E6,3462 GRAPHICS_PARAMETER_ARRAY_TOO_SMALL = 0xC01E05E6,
5080
5081 /// An internal error caused an operation to fail.3463 /// An internal error caused an operation to fail.
5082 GRAPHICS_INTERNAL_ERROR = 0xC01E05E7,3464 GRAPHICS_INTERNAL_ERROR = 0xC01E05E7,
5083
5084 /// The function failed because the current session is changing its type.3465 /// The function failed because the current session is changing its type.
5085 /// This function cannot be called when the current session is changing its type.3466 /// This function cannot be called when the current session is changing its type.
5086 /// Three types of sessions currently exist: console, disconnected, and remote (RDP or ICA).3467 /// Three types of sessions currently exist: console, disconnected, and remote (RDP or ICA).
5087 GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS = 0xC01E05E8,3468 GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS = 0xC01E05E8,
5088
5089 /// The volume must be unlocked before it can be used.3469 /// The volume must be unlocked before it can be used.
5090 FVE_LOCKED_VOLUME = 0xC0210000,3470 FVE_LOCKED_VOLUME = 0xC0210000,
5091
5092 /// The volume is fully decrypted and no key is available.3471 /// The volume is fully decrypted and no key is available.
5093 FVE_NOT_ENCRYPTED = 0xC0210001,3472 FVE_NOT_ENCRYPTED = 0xC0210001,
5094
5095 /// The control block for the encrypted volume is not valid.3473 /// The control block for the encrypted volume is not valid.
5096 FVE_BAD_INFORMATION = 0xC0210002,3474 FVE_BAD_INFORMATION = 0xC0210002,
5097
5098 /// Not enough free space remains on the volume to allow encryption.3475 /// Not enough free space remains on the volume to allow encryption.
5099 FVE_TOO_SMALL = 0xC0210003,3476 FVE_TOO_SMALL = 0xC0210003,
5100
5101 /// The partition cannot be encrypted because the file system is not supported.3477 /// The partition cannot be encrypted because the file system is not supported.
5102 FVE_FAILED_WRONG_FS = 0xC0210004,3478 FVE_FAILED_WRONG_FS = 0xC0210004,
5103
5104 /// The file system is inconsistent. Run the Check Disk utility.3479 /// The file system is inconsistent. Run the Check Disk utility.
5105 FVE_FAILED_BAD_FS = 0xC0210005,3480 FVE_FAILED_BAD_FS = 0xC0210005,
5106
5107 /// The file system does not extend to the end of the volume.3481 /// The file system does not extend to the end of the volume.
5108 FVE_FS_NOT_EXTENDED = 0xC0210006,3482 FVE_FS_NOT_EXTENDED = 0xC0210006,
5109
5110 /// This operation cannot be performed while a file system is mounted on the volume.3483 /// This operation cannot be performed while a file system is mounted on the volume.
5111 FVE_FS_MOUNTED = 0xC0210007,3484 FVE_FS_MOUNTED = 0xC0210007,
5112
5113 /// BitLocker Drive Encryption is not included with this version of Windows.3485 /// BitLocker Drive Encryption is not included with this version of Windows.
5114 FVE_NO_LICENSE = 0xC0210008,3486 FVE_NO_LICENSE = 0xC0210008,
5115
5116 /// The requested action was denied by the FVE control engine.3487 /// The requested action was denied by the FVE control engine.
5117 FVE_ACTION_NOT_ALLOWED = 0xC0210009,3488 FVE_ACTION_NOT_ALLOWED = 0xC0210009,
5118
5119 /// The data supplied is malformed.3489 /// The data supplied is malformed.
5120 FVE_BAD_DATA = 0xC021000A,3490 FVE_BAD_DATA = 0xC021000A,
5121
5122 /// The volume is not bound to the system.3491 /// The volume is not bound to the system.
5123 FVE_VOLUME_NOT_BOUND = 0xC021000B,3492 FVE_VOLUME_NOT_BOUND = 0xC021000B,
5124
5125 /// The volume specified is not a data volume.3493 /// The volume specified is not a data volume.
5126 FVE_NOT_DATA_VOLUME = 0xC021000C,3494 FVE_NOT_DATA_VOLUME = 0xC021000C,
5127
5128 /// A read operation failed while converting the volume.3495 /// A read operation failed while converting the volume.
5129 FVE_CONV_READ_ERROR = 0xC021000D,3496 FVE_CONV_READ_ERROR = 0xC021000D,
5130
5131 /// A write operation failed while converting the volume.3497 /// A write operation failed while converting the volume.
5132 FVE_CONV_WRITE_ERROR = 0xC021000E,3498 FVE_CONV_WRITE_ERROR = 0xC021000E,
5133
5134 /// The control block for the encrypted volume was updated by another thread. Try again.3499 /// The control block for the encrypted volume was updated by another thread. Try again.
5135 FVE_OVERLAPPED_UPDATE = 0xC021000F,3500 FVE_OVERLAPPED_UPDATE = 0xC021000F,
5136
5137 /// The volume encryption algorithm cannot be used on this sector size.3501 /// The volume encryption algorithm cannot be used on this sector size.
5138 FVE_FAILED_SECTOR_SIZE = 0xC0210010,3502 FVE_FAILED_SECTOR_SIZE = 0xC0210010,
5139
5140 /// BitLocker recovery authentication failed.3503 /// BitLocker recovery authentication failed.
5141 FVE_FAILED_AUTHENTICATION = 0xC0210011,3504 FVE_FAILED_AUTHENTICATION = 0xC0210011,
5142
5143 /// The volume specified is not the boot operating system volume.3505 /// The volume specified is not the boot operating system volume.
5144 FVE_NOT_OS_VOLUME = 0xC0210012,3506 FVE_NOT_OS_VOLUME = 0xC0210012,
5145
5146 /// The BitLocker startup key or recovery password could not be read from external media.3507 /// The BitLocker startup key or recovery password could not be read from external media.
5147 FVE_KEYFILE_NOT_FOUND = 0xC0210013,3508 FVE_KEYFILE_NOT_FOUND = 0xC0210013,
5148
5149 /// The BitLocker startup key or recovery password file is corrupt or invalid.3509 /// The BitLocker startup key or recovery password file is corrupt or invalid.
5150 FVE_KEYFILE_INVALID = 0xC0210014,3510 FVE_KEYFILE_INVALID = 0xC0210014,
5151
5152 /// The BitLocker encryption key could not be obtained from the startup key or the recovery password.3511 /// The BitLocker encryption key could not be obtained from the startup key or the recovery password.
5153 FVE_KEYFILE_NO_VMK = 0xC0210015,3512 FVE_KEYFILE_NO_VMK = 0xC0210015,
5154
5155 /// The TPM is disabled.3513 /// The TPM is disabled.
5156 FVE_TPM_DISABLED = 0xC0210016,3514 FVE_TPM_DISABLED = 0xC0210016,
5157
5158 /// The authorization data for the SRK of the TPM is not zero.3515 /// The authorization data for the SRK of the TPM is not zero.
5159 FVE_TPM_SRK_AUTH_NOT_ZERO = 0xC0210017,3516 FVE_TPM_SRK_AUTH_NOT_ZERO = 0xC0210017,
5160
5161 /// The system boot information changed or the TPM locked out access to BitLocker encryption keys until the computer is restarted.3517 /// The system boot information changed or the TPM locked out access to BitLocker encryption keys until the computer is restarted.
5162 FVE_TPM_INVALID_PCR = 0xC0210018,3518 FVE_TPM_INVALID_PCR = 0xC0210018,
5163
5164 /// The BitLocker encryption key could not be obtained from the TPM.3519 /// The BitLocker encryption key could not be obtained from the TPM.
5165 FVE_TPM_NO_VMK = 0xC0210019,3520 FVE_TPM_NO_VMK = 0xC0210019,
5166
5167 /// The BitLocker encryption key could not be obtained from the TPM and PIN.3521 /// The BitLocker encryption key could not be obtained from the TPM and PIN.
5168 FVE_PIN_INVALID = 0xC021001A,3522 FVE_PIN_INVALID = 0xC021001A,
5169
5170 /// A boot application hash does not match the hash computed when BitLocker was turned on.3523 /// A boot application hash does not match the hash computed when BitLocker was turned on.
5171 FVE_AUTH_INVALID_APPLICATION = 0xC021001B,3524 FVE_AUTH_INVALID_APPLICATION = 0xC021001B,
5172
5173 /// The Boot Configuration Data (BCD) settings are not supported or have changed because BitLocker was enabled.3525 /// The Boot Configuration Data (BCD) settings are not supported or have changed because BitLocker was enabled.
5174 FVE_AUTH_INVALID_CONFIG = 0xC021001C,3526 FVE_AUTH_INVALID_CONFIG = 0xC021001C,
5175
5176 /// Boot debugging is enabled. Run Windows Boot Configuration Data Store Editor (bcdedit.exe) to turn it off.3527 /// Boot debugging is enabled. Run Windows Boot Configuration Data Store Editor (bcdedit.exe) to turn it off.
5177 FVE_DEBUGGER_ENABLED = 0xC021001D,3528 FVE_DEBUGGER_ENABLED = 0xC021001D,
5178
5179 /// The BitLocker encryption key could not be obtained.3529 /// The BitLocker encryption key could not be obtained.
5180 FVE_DRY_RUN_FAILED = 0xC021001E,3530 FVE_DRY_RUN_FAILED = 0xC021001E,
5181
5182 /// The metadata disk region pointer is incorrect.3531 /// The metadata disk region pointer is incorrect.
5183 FVE_BAD_METADATA_POINTER = 0xC021001F,3532 FVE_BAD_METADATA_POINTER = 0xC021001F,
5184
5185 /// The backup copy of the metadata is out of date.3533 /// The backup copy of the metadata is out of date.
5186 FVE_OLD_METADATA_COPY = 0xC0210020,3534 FVE_OLD_METADATA_COPY = 0xC0210020,
5187
5188 /// No action was taken because a system restart is required.3535 /// No action was taken because a system restart is required.
5189 FVE_REBOOT_REQUIRED = 0xC0210021,3536 FVE_REBOOT_REQUIRED = 0xC0210021,
5190
5191 /// No action was taken because BitLocker Drive Encryption is in RAW access mode.3537 /// No action was taken because BitLocker Drive Encryption is in RAW access mode.
5192 FVE_RAW_ACCESS = 0xC0210022,3538 FVE_RAW_ACCESS = 0xC0210022,
5193
5194 /// BitLocker Drive Encryption cannot enter RAW access mode for this volume.3539 /// BitLocker Drive Encryption cannot enter RAW access mode for this volume.
5195 FVE_RAW_BLOCKED = 0xC0210023,3540 FVE_RAW_BLOCKED = 0xC0210023,
5196
5197 /// This feature of BitLocker Drive Encryption is not included with this version of Windows.3541 /// This feature of BitLocker Drive Encryption is not included with this version of Windows.
5198 FVE_NO_FEATURE_LICENSE = 0xC0210026,3542 FVE_NO_FEATURE_LICENSE = 0xC0210026,
5199
5200 /// Group policy does not permit turning off BitLocker Drive Encryption on roaming data volumes.3543 /// Group policy does not permit turning off BitLocker Drive Encryption on roaming data volumes.
5201 FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED = 0xC0210027,3544 FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED = 0xC0210027,
5202
5203 /// Bitlocker Drive Encryption failed to recover from aborted conversion.3545 /// Bitlocker Drive Encryption failed to recover from aborted conversion.
5204 /// This could be due to either all conversion logs being corrupted or the media being write-protected.3546 /// This could be due to either all conversion logs being corrupted or the media being write-protected.
5205 FVE_CONV_RECOVERY_FAILED = 0xC0210028,3547 FVE_CONV_RECOVERY_FAILED = 0xC0210028,
5206
5207 /// The requested virtualization size is too big.3548 /// The requested virtualization size is too big.
5208 FVE_VIRTUALIZED_SPACE_TOO_BIG = 0xC0210029,3549 FVE_VIRTUALIZED_SPACE_TOO_BIG = 0xC0210029,
5209
5210 /// The drive is too small to be protected using BitLocker Drive Encryption.3550 /// The drive is too small to be protected using BitLocker Drive Encryption.
5211 FVE_VOLUME_TOO_SMALL = 0xC0210030,3551 FVE_VOLUME_TOO_SMALL = 0xC0210030,
5212
5213 /// The callout does not exist.3552 /// The callout does not exist.
5214 FWP_CALLOUT_NOT_FOUND = 0xC0220001,3553 FWP_CALLOUT_NOT_FOUND = 0xC0220001,
5215
5216 /// The filter condition does not exist.3554 /// The filter condition does not exist.
5217 FWP_CONDITION_NOT_FOUND = 0xC0220002,3555 FWP_CONDITION_NOT_FOUND = 0xC0220002,
5218
5219 /// The filter does not exist.3556 /// The filter does not exist.
5220 FWP_FILTER_NOT_FOUND = 0xC0220003,3557 FWP_FILTER_NOT_FOUND = 0xC0220003,
5221
5222 /// The layer does not exist.3558 /// The layer does not exist.
5223 FWP_LAYER_NOT_FOUND = 0xC0220004,3559 FWP_LAYER_NOT_FOUND = 0xC0220004,
5224
5225 /// The provider does not exist.3560 /// The provider does not exist.
5226 FWP_PROVIDER_NOT_FOUND = 0xC0220005,3561 FWP_PROVIDER_NOT_FOUND = 0xC0220005,
5227
5228 /// The provider context does not exist.3562 /// The provider context does not exist.
5229 FWP_PROVIDER_CONTEXT_NOT_FOUND = 0xC0220006,3563 FWP_PROVIDER_CONTEXT_NOT_FOUND = 0xC0220006,
5230
5231 /// The sublayer does not exist.3564 /// The sublayer does not exist.
5232 FWP_SUBLAYER_NOT_FOUND = 0xC0220007,3565 FWP_SUBLAYER_NOT_FOUND = 0xC0220007,
5233
5234 /// The object does not exist.3566 /// The object does not exist.
5235 FWP_NOT_FOUND = 0xC0220008,3567 FWP_NOT_FOUND = 0xC0220008,
5236
5237 /// An object with that GUID or LUID already exists.3568 /// An object with that GUID or LUID already exists.
5238 FWP_ALREADY_EXISTS = 0xC0220009,3569 FWP_ALREADY_EXISTS = 0xC0220009,
5239
5240 /// The object is referenced by other objects and cannot be deleted.3570 /// The object is referenced by other objects and cannot be deleted.
5241 FWP_IN_USE = 0xC022000A,3571 FWP_IN_USE = 0xC022000A,
5242
5243 /// The call is not allowed from within a dynamic session.3572 /// The call is not allowed from within a dynamic session.
5244 FWP_DYNAMIC_SESSION_IN_PROGRESS = 0xC022000B,3573 FWP_DYNAMIC_SESSION_IN_PROGRESS = 0xC022000B,
5245
5246 /// The call was made from the wrong session and cannot be completed.3574 /// The call was made from the wrong session and cannot be completed.
5247 FWP_WRONG_SESSION = 0xC022000C,3575 FWP_WRONG_SESSION = 0xC022000C,
5248
5249 /// The call must be made from within an explicit transaction.3576 /// The call must be made from within an explicit transaction.
5250 FWP_NO_TXN_IN_PROGRESS = 0xC022000D,3577 FWP_NO_TXN_IN_PROGRESS = 0xC022000D,
5251
5252 /// The call is not allowed from within an explicit transaction.3578 /// The call is not allowed from within an explicit transaction.
5253 FWP_TXN_IN_PROGRESS = 0xC022000E,3579 FWP_TXN_IN_PROGRESS = 0xC022000E,
5254
5255 /// The explicit transaction has been forcibly canceled.3580 /// The explicit transaction has been forcibly canceled.
5256 FWP_TXN_ABORTED = 0xC022000F,3581 FWP_TXN_ABORTED = 0xC022000F,
5257
5258 /// The session has been canceled.3582 /// The session has been canceled.
5259 FWP_SESSION_ABORTED = 0xC0220010,3583 FWP_SESSION_ABORTED = 0xC0220010,
5260
5261 /// The call is not allowed from within a read-only transaction.3584 /// The call is not allowed from within a read-only transaction.
5262 FWP_INCOMPATIBLE_TXN = 0xC0220011,3585 FWP_INCOMPATIBLE_TXN = 0xC0220011,
5263
5264 /// The call timed out while waiting to acquire the transaction lock.3586 /// The call timed out while waiting to acquire the transaction lock.
5265 FWP_TIMEOUT = 0xC0220012,3587 FWP_TIMEOUT = 0xC0220012,
5266
5267 /// The collection of network diagnostic events is disabled.3588 /// The collection of network diagnostic events is disabled.
5268 FWP_NET_EVENTS_DISABLED = 0xC0220013,3589 FWP_NET_EVENTS_DISABLED = 0xC0220013,
5269
5270 /// The operation is not supported by the specified layer.3590 /// The operation is not supported by the specified layer.
5271 FWP_INCOMPATIBLE_LAYER = 0xC0220014,3591 FWP_INCOMPATIBLE_LAYER = 0xC0220014,
5272
5273 /// The call is allowed for kernel-mode callers only.3592 /// The call is allowed for kernel-mode callers only.
5274 FWP_KM_CLIENTS_ONLY = 0xC0220015,3593 FWP_KM_CLIENTS_ONLY = 0xC0220015,
5275
5276 /// The call tried to associate two objects with incompatible lifetimes.3594 /// The call tried to associate two objects with incompatible lifetimes.
5277 FWP_LIFETIME_MISMATCH = 0xC0220016,3595 FWP_LIFETIME_MISMATCH = 0xC0220016,
5278
5279 /// The object is built-in and cannot be deleted.3596 /// The object is built-in and cannot be deleted.
5280 FWP_BUILTIN_OBJECT = 0xC0220017,3597 FWP_BUILTIN_OBJECT = 0xC0220017,
5281
5282 /// The maximum number of boot-time filters has been reached.
5283 FWP_TOO_MANY_BOOTTIME_FILTERS = 0xC0220018,
5284
5285 /// The maximum number of callouts has been reached.3598 /// The maximum number of callouts has been reached.
5286 FWP_TOO_MANY_CALLOUTS = 0xC0220018,3599 FWP_TOO_MANY_CALLOUTS = 0xC0220018,
5287
5288 /// A notification could not be delivered because a message queue has reached maximum capacity.3600 /// A notification could not be delivered because a message queue has reached maximum capacity.
5289 FWP_NOTIFICATION_DROPPED = 0xC0220019,3601 FWP_NOTIFICATION_DROPPED = 0xC0220019,
5290
5291 /// The traffic parameters do not match those for the security association context.3602 /// The traffic parameters do not match those for the security association context.
5292 FWP_TRAFFIC_MISMATCH = 0xC022001A,3603 FWP_TRAFFIC_MISMATCH = 0xC022001A,
5293
5294 /// The call is not allowed for the current security association state.3604 /// The call is not allowed for the current security association state.
5295 FWP_INCOMPATIBLE_SA_STATE = 0xC022001B,3605 FWP_INCOMPATIBLE_SA_STATE = 0xC022001B,
5296
5297 /// A required pointer is null.3606 /// A required pointer is null.
5298 FWP_NULL_POINTER = 0xC022001C,3607 FWP_NULL_POINTER = 0xC022001C,
5299
5300 /// An enumerator is not valid.3608 /// An enumerator is not valid.
5301 FWP_INVALID_ENUMERATOR = 0xC022001D,3609 FWP_INVALID_ENUMERATOR = 0xC022001D,
5302
5303 /// The flags field contains an invalid value.3610 /// The flags field contains an invalid value.
5304 FWP_INVALID_FLAGS = 0xC022001E,3611 FWP_INVALID_FLAGS = 0xC022001E,
5305
5306 /// A network mask is not valid.3612 /// A network mask is not valid.
5307 FWP_INVALID_NET_MASK = 0xC022001F,3613 FWP_INVALID_NET_MASK = 0xC022001F,
5308
5309 /// An FWP_RANGE is not valid.3614 /// An FWP_RANGE is not valid.
5310 FWP_INVALID_RANGE = 0xC0220020,3615 FWP_INVALID_RANGE = 0xC0220020,
5311
5312 /// The time interval is not valid.3616 /// The time interval is not valid.
5313 FWP_INVALID_INTERVAL = 0xC0220021,3617 FWP_INVALID_INTERVAL = 0xC0220021,
5314
5315 /// An array that must contain at least one element has a zero length.3618 /// An array that must contain at least one element has a zero length.
5316 FWP_ZERO_LENGTH_ARRAY = 0xC0220022,3619 FWP_ZERO_LENGTH_ARRAY = 0xC0220022,
5317
5318 /// The displayData.name field cannot be null.3620 /// The displayData.name field cannot be null.
5319 FWP_NULL_DISPLAY_NAME = 0xC0220023,3621 FWP_NULL_DISPLAY_NAME = 0xC0220023,
5320
5321 /// The action type is not one of the allowed action types for a filter.3622 /// The action type is not one of the allowed action types for a filter.
5322 FWP_INVALID_ACTION_TYPE = 0xC0220024,3623 FWP_INVALID_ACTION_TYPE = 0xC0220024,
5323
5324 /// The filter weight is not valid.3624 /// The filter weight is not valid.
5325 FWP_INVALID_WEIGHT = 0xC0220025,3625 FWP_INVALID_WEIGHT = 0xC0220025,
5326
5327 /// A filter condition contains a match type that is not compatible with the operands.3626 /// A filter condition contains a match type that is not compatible with the operands.
5328 FWP_MATCH_TYPE_MISMATCH = 0xC0220026,3627 FWP_MATCH_TYPE_MISMATCH = 0xC0220026,
5329
5330 /// An FWP_VALUE or FWPM_CONDITION_VALUE is of the wrong type.3628 /// An FWP_VALUE or FWPM_CONDITION_VALUE is of the wrong type.
5331 FWP_TYPE_MISMATCH = 0xC0220027,3629 FWP_TYPE_MISMATCH = 0xC0220027,
5332
5333 /// An integer value is outside the allowed range.3630 /// An integer value is outside the allowed range.
5334 FWP_OUT_OF_BOUNDS = 0xC0220028,3631 FWP_OUT_OF_BOUNDS = 0xC0220028,
5335
5336 /// A reserved field is nonzero.3632 /// A reserved field is nonzero.
5337 FWP_RESERVED = 0xC0220029,3633 FWP_RESERVED = 0xC0220029,
5338
5339 /// A filter cannot contain multiple conditions operating on a single field.3634 /// A filter cannot contain multiple conditions operating on a single field.
5340 FWP_DUPLICATE_CONDITION = 0xC022002A,3635 FWP_DUPLICATE_CONDITION = 0xC022002A,
5341
5342 /// A policy cannot contain the same keying module more than once.3636 /// A policy cannot contain the same keying module more than once.
5343 FWP_DUPLICATE_KEYMOD = 0xC022002B,3637 FWP_DUPLICATE_KEYMOD = 0xC022002B,
5344
5345 /// The action type is not compatible with the layer.3638 /// The action type is not compatible with the layer.
5346 FWP_ACTION_INCOMPATIBLE_WITH_LAYER = 0xC022002C,3639 FWP_ACTION_INCOMPATIBLE_WITH_LAYER = 0xC022002C,
5347
5348 /// The action type is not compatible with the sublayer.3640 /// The action type is not compatible with the sublayer.
5349 FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER = 0xC022002D,3641 FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER = 0xC022002D,
5350
5351 /// The raw context or the provider context is not compatible with the layer.3642 /// The raw context or the provider context is not compatible with the layer.
5352 FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER = 0xC022002E,3643 FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER = 0xC022002E,
5353
5354 /// The raw context or the provider context is not compatible with the callout.3644 /// The raw context or the provider context is not compatible with the callout.
5355 FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT = 0xC022002F,3645 FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT = 0xC022002F,
5356
5357 /// The authentication method is not compatible with the policy type.3646 /// The authentication method is not compatible with the policy type.
5358 FWP_INCOMPATIBLE_AUTH_METHOD = 0xC0220030,3647 FWP_INCOMPATIBLE_AUTH_METHOD = 0xC0220030,
5359
5360 /// The Diffie-Hellman group is not compatible with the policy type.3648 /// The Diffie-Hellman group is not compatible with the policy type.
5361 FWP_INCOMPATIBLE_DH_GROUP = 0xC0220031,3649 FWP_INCOMPATIBLE_DH_GROUP = 0xC0220031,
5362
5363 /// An IKE policy cannot contain an Extended Mode policy.3650 /// An IKE policy cannot contain an Extended Mode policy.
5364 FWP_EM_NOT_SUPPORTED = 0xC0220032,3651 FWP_EM_NOT_SUPPORTED = 0xC0220032,
5365
5366 /// The enumeration template or subscription will never match any objects.3652 /// The enumeration template or subscription will never match any objects.
5367 FWP_NEVER_MATCH = 0xC0220033,3653 FWP_NEVER_MATCH = 0xC0220033,
5368
5369 /// The provider context is of the wrong type.3654 /// The provider context is of the wrong type.
5370 FWP_PROVIDER_CONTEXT_MISMATCH = 0xC0220034,3655 FWP_PROVIDER_CONTEXT_MISMATCH = 0xC0220034,
5371
5372 /// The parameter is incorrect.3656 /// The parameter is incorrect.
5373 FWP_INVALID_PARAMETER = 0xC0220035,3657 FWP_INVALID_PARAMETER = 0xC0220035,
5374
5375 /// The maximum number of sublayers has been reached.3658 /// The maximum number of sublayers has been reached.
5376 FWP_TOO_MANY_SUBLAYERS = 0xC0220036,3659 FWP_TOO_MANY_SUBLAYERS = 0xC0220036,
5377
5378 /// The notification function for a callout returned an error.3660 /// The notification function for a callout returned an error.
5379 FWP_CALLOUT_NOTIFICATION_FAILED = 0xC0220037,3661 FWP_CALLOUT_NOTIFICATION_FAILED = 0xC0220037,
5380
5381 /// The IPsec authentication configuration is not compatible with the authentication type.3662 /// The IPsec authentication configuration is not compatible with the authentication type.
5382 FWP_INCOMPATIBLE_AUTH_CONFIG = 0xC0220038,3663 FWP_INCOMPATIBLE_AUTH_CONFIG = 0xC0220038,
5383
5384 /// The IPsec cipher configuration is not compatible with the cipher type.3664 /// The IPsec cipher configuration is not compatible with the cipher type.
5385 FWP_INCOMPATIBLE_CIPHER_CONFIG = 0xC0220039,3665 FWP_INCOMPATIBLE_CIPHER_CONFIG = 0xC0220039,
5386
5387 /// A policy cannot contain the same auth method more than once.3666 /// A policy cannot contain the same auth method more than once.
5388 FWP_DUPLICATE_AUTH_METHOD = 0xC022003C,3667 FWP_DUPLICATE_AUTH_METHOD = 0xC022003C,
5389
5390 /// The TCP/IP stack is not ready.3668 /// The TCP/IP stack is not ready.
5391 FWP_TCPIP_NOT_READY = 0xC0220100,3669 FWP_TCPIP_NOT_READY = 0xC0220100,
5392
5393 /// The injection handle is being closed by another thread.3670 /// The injection handle is being closed by another thread.
5394 FWP_INJECT_HANDLE_CLOSING = 0xC0220101,3671 FWP_INJECT_HANDLE_CLOSING = 0xC0220101,
5395
5396 /// The injection handle is stale.3672 /// The injection handle is stale.
5397 FWP_INJECT_HANDLE_STALE = 0xC0220102,3673 FWP_INJECT_HANDLE_STALE = 0xC0220102,
5398
5399 /// The classify cannot be pended.3674 /// The classify cannot be pended.
5400 FWP_CANNOT_PEND = 0xC0220103,3675 FWP_CANNOT_PEND = 0xC0220103,
5401
5402 /// The binding to the network interface is being closed.3676 /// The binding to the network interface is being closed.
5403 NDIS_CLOSING = 0xC0230002,3677 NDIS_CLOSING = 0xC0230002,
5404
5405 /// An invalid version was specified.3678 /// An invalid version was specified.
5406 NDIS_BAD_VERSION = 0xC0230004,3679 NDIS_BAD_VERSION = 0xC0230004,
5407
5408 /// An invalid characteristics table was used.3680 /// An invalid characteristics table was used.
5409 NDIS_BAD_CHARACTERISTICS = 0xC0230005,3681 NDIS_BAD_CHARACTERISTICS = 0xC0230005,
5410
5411 /// Failed to find the network interface or the network interface is not ready.3682 /// Failed to find the network interface or the network interface is not ready.
5412 NDIS_ADAPTER_NOT_FOUND = 0xC0230006,3683 NDIS_ADAPTER_NOT_FOUND = 0xC0230006,
5413
5414 /// Failed to open the network interface.3684 /// Failed to open the network interface.
5415 NDIS_OPEN_FAILED = 0xC0230007,3685 NDIS_OPEN_FAILED = 0xC0230007,
5416
5417 /// The network interface has encountered an internal unrecoverable failure.3686 /// The network interface has encountered an internal unrecoverable failure.
5418 NDIS_DEVICE_FAILED = 0xC0230008,3687 NDIS_DEVICE_FAILED = 0xC0230008,
5419
5420 /// The multicast list on the network interface is full.3688 /// The multicast list on the network interface is full.
5421 NDIS_MULTICAST_FULL = 0xC0230009,3689 NDIS_MULTICAST_FULL = 0xC0230009,
5422
5423 /// An attempt was made to add a duplicate multicast address to the list.3690 /// An attempt was made to add a duplicate multicast address to the list.
5424 NDIS_MULTICAST_EXISTS = 0xC023000A,3691 NDIS_MULTICAST_EXISTS = 0xC023000A,
5425
5426 /// At attempt was made to remove a multicast address that was never added.3692 /// At attempt was made to remove a multicast address that was never added.
5427 NDIS_MULTICAST_NOT_FOUND = 0xC023000B,3693 NDIS_MULTICAST_NOT_FOUND = 0xC023000B,
5428
5429 /// The network interface aborted the request.3694 /// The network interface aborted the request.
5430 NDIS_REQUEST_ABORTED = 0xC023000C,3695 NDIS_REQUEST_ABORTED = 0xC023000C,
5431
5432 /// The network interface cannot process the request because it is being reset.3696 /// The network interface cannot process the request because it is being reset.
5433 NDIS_RESET_IN_PROGRESS = 0xC023000D,3697 NDIS_RESET_IN_PROGRESS = 0xC023000D,
5434
5435 /// An attempt was made to send an invalid packet on a network interface.3698 /// An attempt was made to send an invalid packet on a network interface.
5436 NDIS_INVALID_PACKET = 0xC023000F,3699 NDIS_INVALID_PACKET = 0xC023000F,
5437
5438 /// The specified request is not a valid operation for the target device.3700 /// The specified request is not a valid operation for the target device.
5439 NDIS_INVALID_DEVICE_REQUEST = 0xC0230010,3701 NDIS_INVALID_DEVICE_REQUEST = 0xC0230010,
5440
5441 /// The network interface is not ready to complete this operation.3702 /// The network interface is not ready to complete this operation.
5442 NDIS_ADAPTER_NOT_READY = 0xC0230011,3703 NDIS_ADAPTER_NOT_READY = 0xC0230011,
5443
5444 /// The length of the buffer submitted for this operation is not valid.3704 /// The length of the buffer submitted for this operation is not valid.
5445 NDIS_INVALID_LENGTH = 0xC0230014,3705 NDIS_INVALID_LENGTH = 0xC0230014,
5446
5447 /// The data used for this operation is not valid.3706 /// The data used for this operation is not valid.
5448 NDIS_INVALID_DATA = 0xC0230015,3707 NDIS_INVALID_DATA = 0xC0230015,
5449
5450 /// The length of the submitted buffer for this operation is too small.3708 /// The length of the submitted buffer for this operation is too small.
5451 NDIS_BUFFER_TOO_SHORT = 0xC0230016,3709 NDIS_BUFFER_TOO_SHORT = 0xC0230016,
5452
5453 /// The network interface does not support this object identifier.3710 /// The network interface does not support this object identifier.
5454 NDIS_INVALID_OID = 0xC0230017,3711 NDIS_INVALID_OID = 0xC0230017,
5455
5456 /// The network interface has been removed.3712 /// The network interface has been removed.
5457 NDIS_ADAPTER_REMOVED = 0xC0230018,3713 NDIS_ADAPTER_REMOVED = 0xC0230018,
5458
5459 /// The network interface does not support this media type.3714 /// The network interface does not support this media type.
5460 NDIS_UNSUPPORTED_MEDIA = 0xC0230019,3715 NDIS_UNSUPPORTED_MEDIA = 0xC0230019,
5461
5462 /// An attempt was made to remove a token ring group address that is in use by other components.3716 /// An attempt was made to remove a token ring group address that is in use by other components.
5463 NDIS_GROUP_ADDRESS_IN_USE = 0xC023001A,3717 NDIS_GROUP_ADDRESS_IN_USE = 0xC023001A,
5464
5465 /// An attempt was made to map a file that cannot be found.3718 /// An attempt was made to map a file that cannot be found.
5466 NDIS_FILE_NOT_FOUND = 0xC023001B,3719 NDIS_FILE_NOT_FOUND = 0xC023001B,
5467
5468 /// An error occurred while NDIS tried to map the file.3720 /// An error occurred while NDIS tried to map the file.
5469 NDIS_ERROR_READING_FILE = 0xC023001C,3721 NDIS_ERROR_READING_FILE = 0xC023001C,
5470
5471 /// An attempt was made to map a file that is already mapped.3722 /// An attempt was made to map a file that is already mapped.
5472 NDIS_ALREADY_MAPPED = 0xC023001D,3723 NDIS_ALREADY_MAPPED = 0xC023001D,
5473
5474 /// An attempt to allocate a hardware resource failed because the resource is used by another component.3724 /// An attempt to allocate a hardware resource failed because the resource is used by another component.
5475 NDIS_RESOURCE_CONFLICT = 0xC023001E,3725 NDIS_RESOURCE_CONFLICT = 0xC023001E,
5476
5477 /// The I/O operation failed because the network media is disconnected or the wireless access point is out of range.3726 /// The I/O operation failed because the network media is disconnected or the wireless access point is out of range.
5478 NDIS_MEDIA_DISCONNECTED = 0xC023001F,3727 NDIS_MEDIA_DISCONNECTED = 0xC023001F,
5479
5480 /// The network address used in the request is invalid.3728 /// The network address used in the request is invalid.
5481 NDIS_INVALID_ADDRESS = 0xC0230022,3729 NDIS_INVALID_ADDRESS = 0xC0230022,
5482
5483 /// The offload operation on the network interface has been paused.3730 /// The offload operation on the network interface has been paused.
5484 NDIS_PAUSED = 0xC023002A,3731 NDIS_PAUSED = 0xC023002A,
5485
5486 /// The network interface was not found.3732 /// The network interface was not found.
5487 NDIS_INTERFACE_NOT_FOUND = 0xC023002B,3733 NDIS_INTERFACE_NOT_FOUND = 0xC023002B,
5488
5489 /// The revision number specified in the structure is not supported.3734 /// The revision number specified in the structure is not supported.
5490 NDIS_UNSUPPORTED_REVISION = 0xC023002C,3735 NDIS_UNSUPPORTED_REVISION = 0xC023002C,
5491
5492 /// The specified port does not exist on this network interface.3736 /// The specified port does not exist on this network interface.
5493 NDIS_INVALID_PORT = 0xC023002D,3737 NDIS_INVALID_PORT = 0xC023002D,
5494
5495 /// The current state of the specified port on this network interface does not support the requested operation.3738 /// The current state of the specified port on this network interface does not support the requested operation.
5496 NDIS_INVALID_PORT_STATE = 0xC023002E,3739 NDIS_INVALID_PORT_STATE = 0xC023002E,
5497
5498 /// The miniport adapter is in a lower power state.3740 /// The miniport adapter is in a lower power state.
5499 NDIS_LOW_POWER_STATE = 0xC023002F,3741 NDIS_LOW_POWER_STATE = 0xC023002F,
5500
5501 /// The network interface does not support this request.3742 /// The network interface does not support this request.
5502 NDIS_NOT_SUPPORTED = 0xC02300BB,3743 NDIS_NOT_SUPPORTED = 0xC02300BB,
5503
5504 /// The TCP connection is not offloadable because of a local policy setting.3744 /// The TCP connection is not offloadable because of a local policy setting.
5505 NDIS_OFFLOAD_POLICY = 0xC023100F,3745 NDIS_OFFLOAD_POLICY = 0xC023100F,
5506
5507 /// The TCP connection is not offloadable by the Chimney offload target.3746 /// The TCP connection is not offloadable by the Chimney offload target.
5508 NDIS_OFFLOAD_CONNECTION_REJECTED = 0xC0231012,3747 NDIS_OFFLOAD_CONNECTION_REJECTED = 0xC0231012,
5509
5510 /// The IP Path object is not in an offloadable state.3748 /// The IP Path object is not in an offloadable state.
5511 NDIS_OFFLOAD_PATH_REJECTED = 0xC0231013,3749 NDIS_OFFLOAD_PATH_REJECTED = 0xC0231013,
5512
5513 /// The wireless LAN interface is in auto-configuration mode and does not support the requested parameter change operation.3750 /// The wireless LAN interface is in auto-configuration mode and does not support the requested parameter change operation.
5514 NDIS_DOT11_AUTO_CONFIG_ENABLED = 0xC0232000,3751 NDIS_DOT11_AUTO_CONFIG_ENABLED = 0xC0232000,
5515
5516 /// The wireless LAN interface is busy and cannot perform the requested operation.3752 /// The wireless LAN interface is busy and cannot perform the requested operation.
5517 NDIS_DOT11_MEDIA_IN_USE = 0xC0232001,3753 NDIS_DOT11_MEDIA_IN_USE = 0xC0232001,
5518
5519 /// The wireless LAN interface is power down and does not support the requested operation.3754 /// The wireless LAN interface is power down and does not support the requested operation.
5520 NDIS_DOT11_POWER_STATE_INVALID = 0xC0232002,3755 NDIS_DOT11_POWER_STATE_INVALID = 0xC0232002,
5521
5522 /// The list of wake on LAN patterns is full.3756 /// The list of wake on LAN patterns is full.
5523 NDIS_PM_WOL_PATTERN_LIST_FULL = 0xC0232003,3757 NDIS_PM_WOL_PATTERN_LIST_FULL = 0xC0232003,
5524
5525 /// The list of low power protocol offloads is full.3758 /// The list of low power protocol offloads is full.
5526 NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL = 0xC0232004,3759 NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL = 0xC0232004,
5527
5528 /// The SPI in the packet does not match a valid IPsec SA.3760 /// The SPI in the packet does not match a valid IPsec SA.
5529 IPSEC_BAD_SPI = 0xC0360001,3761 IPSEC_BAD_SPI = 0xC0360001,
5530
5531 /// The packet was received on an IPsec SA whose lifetime has expired.3762 /// The packet was received on an IPsec SA whose lifetime has expired.
5532 IPSEC_SA_LIFETIME_EXPIRED = 0xC0360002,3763 IPSEC_SA_LIFETIME_EXPIRED = 0xC0360002,
5533
5534 /// The packet was received on an IPsec SA that does not match the packet characteristics.3764 /// The packet was received on an IPsec SA that does not match the packet characteristics.
5535 IPSEC_WRONG_SA = 0xC0360003,3765 IPSEC_WRONG_SA = 0xC0360003,
5536
5537 /// The packet sequence number replay check failed.3766 /// The packet sequence number replay check failed.
5538 IPSEC_REPLAY_CHECK_FAILED = 0xC0360004,3767 IPSEC_REPLAY_CHECK_FAILED = 0xC0360004,
5539
5540 /// The IPsec header and/or trailer in the packet is invalid.3768 /// The IPsec header and/or trailer in the packet is invalid.
5541 IPSEC_INVALID_PACKET = 0xC0360005,3769 IPSEC_INVALID_PACKET = 0xC0360005,
5542
5543 /// The IPsec integrity check failed.3770 /// The IPsec integrity check failed.
5544 IPSEC_INTEGRITY_CHECK_FAILED = 0xC0360006,3771 IPSEC_INTEGRITY_CHECK_FAILED = 0xC0360006,
5545
5546 /// IPsec dropped a clear text packet.3772 /// IPsec dropped a clear text packet.
5547 IPSEC_CLEAR_TEXT_DROP = 0xC0360007,3773 IPSEC_CLEAR_TEXT_DROP = 0xC0360007,
5548
5549 /// IPsec dropped an incoming ESP packet in authenticated firewall mode. This drop is benign.3774 /// IPsec dropped an incoming ESP packet in authenticated firewall mode. This drop is benign.
5550 IPSEC_AUTH_FIREWALL_DROP = 0xC0360008,3775 IPSEC_AUTH_FIREWALL_DROP = 0xC0360008,
5551
5552 /// IPsec dropped a packet due to DOS throttle.3776 /// IPsec dropped a packet due to DOS throttle.
5553 IPSEC_THROTTLE_DROP = 0xC0360009,3777 IPSEC_THROTTLE_DROP = 0xC0360009,
5554
5555 /// IPsec Dos Protection matched an explicit block rule.3778 /// IPsec Dos Protection matched an explicit block rule.
5556 IPSEC_DOSP_BLOCK = 0xC0368000,3779 IPSEC_DOSP_BLOCK = 0xC0368000,
5557
5558 /// IPsec Dos Protection received an IPsec specific multicast packet which is not allowed.3780 /// IPsec Dos Protection received an IPsec specific multicast packet which is not allowed.
5559 IPSEC_DOSP_RECEIVED_MULTICAST = 0xC0368001,3781 IPSEC_DOSP_RECEIVED_MULTICAST = 0xC0368001,
5560
5561 /// IPsec Dos Protection received an incorrectly formatted packet.3782 /// IPsec Dos Protection received an incorrectly formatted packet.
5562 IPSEC_DOSP_INVALID_PACKET = 0xC0368002,3783 IPSEC_DOSP_INVALID_PACKET = 0xC0368002,
5563
5564 /// IPsec Dos Protection failed to lookup state.3784 /// IPsec Dos Protection failed to lookup state.
5565 IPSEC_DOSP_STATE_LOOKUP_FAILED = 0xC0368003,3785 IPSEC_DOSP_STATE_LOOKUP_FAILED = 0xC0368003,
5566
5567 /// IPsec Dos Protection failed to create state because there are already maximum number of entries allowed by policy.3786 /// IPsec Dos Protection failed to create state because there are already maximum number of entries allowed by policy.
5568 IPSEC_DOSP_MAX_ENTRIES = 0xC0368004,3787 IPSEC_DOSP_MAX_ENTRIES = 0xC0368004,
5569
5570 /// IPsec Dos Protection received an IPsec negotiation packet for a keying module which is not allowed by policy.3788 /// IPsec Dos Protection received an IPsec negotiation packet for a keying module which is not allowed by policy.
5571 IPSEC_DOSP_KEYMOD_NOT_ALLOWED = 0xC0368005,3789 IPSEC_DOSP_KEYMOD_NOT_ALLOWED = 0xC0368005,
5572
5573 /// IPsec Dos Protection failed to create per internal IP ratelimit queue because there is already maximum number of queues allowed by policy.3790 /// IPsec Dos Protection failed to create per internal IP ratelimit queue because there is already maximum number of queues allowed by policy.
5574 IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES = 0xC0368006,3791 IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES = 0xC0368006,
5575
5576 /// The system does not support mirrored volumes.3792 /// The system does not support mirrored volumes.
5577 VOLMGR_MIRROR_NOT_SUPPORTED = 0xC038005B,3793 VOLMGR_MIRROR_NOT_SUPPORTED = 0xC038005B,
5578
5579 /// The system does not support RAID-5 volumes.3794 /// The system does not support RAID-5 volumes.
5580 VOLMGR_RAID5_NOT_SUPPORTED = 0xC038005C,3795 VOLMGR_RAID5_NOT_SUPPORTED = 0xC038005C,
5581
5582 /// A virtual disk support provider for the specified file was not found.3796 /// A virtual disk support provider for the specified file was not found.
5583 VIRTDISK_PROVIDER_NOT_FOUND = 0xC03A0014,3797 VIRTDISK_PROVIDER_NOT_FOUND = 0xC03A0014,
5584
5585 /// The specified disk is not a virtual disk.3798 /// The specified disk is not a virtual disk.
5586 VIRTDISK_NOT_VIRTUAL_DISK = 0xC03A0015,3799 VIRTDISK_NOT_VIRTUAL_DISK = 0xC03A0015,
5587
5588 /// The chain of virtual hard disks is inaccessible.3800 /// The chain of virtual hard disks is inaccessible.
5589 /// The process has not been granted access rights to the parent virtual hard disk for the differencing disk.3801 /// The process has not been granted access rights to the parent virtual hard disk for the differencing disk.
5590 VHD_PARENT_VHD_ACCESS_DENIED = 0xC03A0016,3802 VHD_PARENT_VHD_ACCESS_DENIED = 0xC03A0016,
5591
5592 /// The chain of virtual hard disks is corrupted.3803 /// The chain of virtual hard disks is corrupted.
5593 /// There is a mismatch in the virtual sizes of the parent virtual hard disk and differencing disk.3804 /// There is a mismatch in the virtual sizes of the parent virtual hard disk and differencing disk.
5594 VHD_CHILD_PARENT_SIZE_MISMATCH = 0xC03A0017,3805 VHD_CHILD_PARENT_SIZE_MISMATCH = 0xC03A0017,
5595
5596 /// The chain of virtual hard disks is corrupted.3806 /// The chain of virtual hard disks is corrupted.
5597 /// A differencing disk is indicated in its own parent chain.3807 /// A differencing disk is indicated in its own parent chain.
5598 VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED = 0xC03A0018,3808 VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED = 0xC03A0018,
5599
5600 /// The chain of virtual hard disks is inaccessible.3809 /// The chain of virtual hard disks is inaccessible.
5601 /// There was an error opening a virtual hard disk further up the chain.3810 /// There was an error opening a virtual hard disk further up the chain.
5602 VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT = 0xC03A0019,3811 VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT = 0xC03A0019,
5603
5604 _,3812 _,
5605};3813};
lib/std/os/windows/user32.zig+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5// and substantial portions of the software.5// and substantial portions of the software.
6usingnamespace @import("bits.zig");6usingnamespace @import("bits.zig");
7const std = @import("std");7const std = @import("std");
8const builtin = @import("builtin");8const builtin = std.builtin;
9const assert = std.debug.assert;9const assert = std.debug.assert;
10const windows = @import("../windows.zig");10const windows = @import("../windows.zig");
11const unexpectedError = windows.unexpectedError;11const unexpectedError = windows.unexpectedError;
lib/std/os/windows/win32error.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6// Codes are from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d6// Codes are from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d
7pub const Win32Error = extern enum(u16) {7pub const Win32Error = enum(u16) {
8 /// The operation completed successfully.8 /// The operation completed successfully.
9 SUCCESS = 0,9 SUCCESS = 0,
1010
lib/std/os/windows/ws2_32.zig+1-1
...@@ -1209,7 +1209,7 @@ pub const hostent = extern struct {...@@ -1209,7 +1209,7 @@ pub const hostent = extern struct {
1209};1209};
12101210
1211// https://docs.microsoft.com/en-au/windows/win32/winsock/windows-sockets-error-codes-21211// https://docs.microsoft.com/en-au/windows/win32/winsock/windows-sockets-error-codes-2
1212pub const WinsockError = extern enum(u16) {1212pub const WinsockError = enum(u16) {
1213 /// Specified event object handle is invalid.1213 /// Specified event object handle is invalid.
1214 /// An application attempts to use an event object, but the specified handle is not valid.1214 /// An application attempts to use an event object, but the specified handle is not valid.
1215 WSA_INVALID_HANDLE = 6,1215 WSA_INVALID_HANDLE = 6,
lib/std/packed_int_array.zig+22-20
...@@ -7,8 +7,10 @@ const std = @import("std");...@@ -7,8 +7,10 @@ const std = @import("std");
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const debug = std.debug;8const debug = std.debug;
9const testing = std.testing;9const testing = std.testing;
10const native_endian = builtin.target.cpu.arch.endian();
11const Endian = std.builtin.Endian;
1012
11pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {13pub fn PackedIntIo(comptime Int: type, comptime endian: Endian) type {
12 //The general technique employed here is to cast bytes in the array to a container14 //The general technique employed here is to cast bytes in the array to a container
13 // integer (having bits % 8 == 0) large enough to contain the number of bits we want,15 // integer (having bits % 8 == 0) large enough to contain the number of bits we want,
14 // then we can retrieve or store the new value with a relative minimum of masking16 // then we can retrieve or store the new value with a relative minimum of masking
...@@ -71,7 +73,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {...@@ -71,7 +73,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
71 const value_ptr = @ptrCast(*align(1) const Container, &bytes[start_byte]);73 const value_ptr = @ptrCast(*align(1) const Container, &bytes[start_byte]);
72 var value = value_ptr.*;74 var value = value_ptr.*;
7375
74 if (endian != builtin.endian) value = @byteSwap(Container, value);76 if (endian != native_endian) value = @byteSwap(Container, value);
7577
76 switch (endian) {78 switch (endian) {
77 .Big => {79 .Big => {
...@@ -119,7 +121,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {...@@ -119,7 +121,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
119 const target_ptr = @ptrCast(*align(1) Container, &bytes[start_byte]);121 const target_ptr = @ptrCast(*align(1) Container, &bytes[start_byte]);
120 var target = target_ptr.*;122 var target = target_ptr.*;
121123
122 if (endian != builtin.endian) target = @byteSwap(Container, target);124 if (endian != native_endian) target = @byteSwap(Container, target);
123125
124 //zero the bits we want to replace in the existing bytes126 //zero the bits we want to replace in the existing bytes
125 const inv_mask = @intCast(Container, std.math.maxInt(UnInt)) << keep_shift;127 const inv_mask = @intCast(Container, std.math.maxInt(UnInt)) << keep_shift;
...@@ -129,7 +131,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {...@@ -129,7 +131,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
129 //merge the new value131 //merge the new value
130 target |= value;132 target |= value;
131133
132 if (endian != builtin.endian) target = @byteSwap(Container, target);134 if (endian != native_endian) target = @byteSwap(Container, target);
133135
134 //save it back136 //save it back
135 target_ptr.* = target;137 target_ptr.* = target;
...@@ -151,7 +153,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {...@@ -151,7 +153,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
151 return new_slice;153 return new_slice;
152 }154 }
153155
154 fn sliceCast(bytes: []u8, comptime NewInt: type, comptime new_endian: builtin.Endian, bit_offset: u3, old_len: usize) PackedIntSliceEndian(NewInt, new_endian) {156 fn sliceCast(bytes: []u8, comptime NewInt: type, comptime new_endian: Endian, bit_offset: u3, old_len: usize) PackedIntSliceEndian(NewInt, new_endian) {
155 const new_int_bits = comptime std.meta.bitCount(NewInt);157 const new_int_bits = comptime std.meta.bitCount(NewInt);
156 const New = PackedIntSliceEndian(NewInt, new_endian);158 const New = PackedIntSliceEndian(NewInt, new_endian);
157159
...@@ -172,13 +174,13 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {...@@ -172,13 +174,13 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
172/// are packed using native endianess and without storing any meta174/// are packed using native endianess and without storing any meta
173/// data. PackedIntArray(i3, 8) will occupy exactly 3 bytes of memory.175/// data. PackedIntArray(i3, 8) will occupy exactly 3 bytes of memory.
174pub fn PackedIntArray(comptime Int: type, comptime int_count: usize) type {176pub fn PackedIntArray(comptime Int: type, comptime int_count: usize) type {
175 return PackedIntArrayEndian(Int, builtin.endian, int_count);177 return PackedIntArrayEndian(Int, native_endian, int_count);
176}178}
177179
178///Creates a bit-packed array of integers of type Int. Bits180///Creates a bit-packed array of integers of type Int. Bits
179/// are packed using specified endianess and without storing any meta181/// are packed using specified endianess and without storing any meta
180/// data.182/// data.
181pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: builtin.Endian, comptime int_count: usize) type {183pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: Endian, comptime int_count: usize) type {
182 const int_bits = comptime std.meta.bitCount(Int);184 const int_bits = comptime std.meta.bitCount(Int);
183 const total_bits = int_bits * int_count;185 const total_bits = int_bits * int_count;
184 const total_bytes = (total_bits + 7) / 8;186 const total_bytes = (total_bits + 7) / 8;
...@@ -247,7 +249,7 @@ pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: builtin.Endian,...@@ -247,7 +249,7 @@ pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: builtin.Endian,
247 ///Create a PackedIntSlice of the array using NewInt as the bit width integer249 ///Create a PackedIntSlice of the array using NewInt as the bit width integer
248 /// and new_endian as the new endianess. NewInt's bit width must fit evenly within250 /// and new_endian as the new endianess. NewInt's bit width must fit evenly within
249 /// the array's Int's total bits.251 /// the array's Int's total bits.
250 pub fn sliceCastEndian(self: *Self, comptime NewInt: type, comptime new_endian: builtin.Endian) PackedIntSliceEndian(NewInt, new_endian) {252 pub fn sliceCastEndian(self: *Self, comptime NewInt: type, comptime new_endian: Endian) PackedIntSliceEndian(NewInt, new_endian) {
251 return Io.sliceCast(&self.bytes, NewInt, new_endian, 0, int_count);253 return Io.sliceCast(&self.bytes, NewInt, new_endian, 0, int_count);
252 }254 }
253 };255 };
...@@ -257,13 +259,13 @@ pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: builtin.Endian,...@@ -257,13 +259,13 @@ pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: builtin.Endian,
257/// Bits are packed using native endianess and without storing any meta259/// Bits are packed using native endianess and without storing any meta
258/// data.260/// data.
259pub fn PackedIntSlice(comptime Int: type) type {261pub fn PackedIntSlice(comptime Int: type) type {
260 return PackedIntSliceEndian(Int, builtin.endian);262 return PackedIntSliceEndian(Int, native_endian);
261}263}
262264
263///Uses a slice as a bit-packed block of int_count integers of type Int.265///Uses a slice as a bit-packed block of int_count integers of type Int.
264/// Bits are packed using specified endianess and without storing any meta266/// Bits are packed using specified endianess and without storing any meta
265/// data.267/// data.
266pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian) type {268pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: Endian) type {
267 const int_bits = comptime std.meta.bitCount(Int);269 const int_bits = comptime std.meta.bitCount(Int);
268 const Io = PackedIntIo(Int, endian);270 const Io = PackedIntIo(Int, endian);
269271
...@@ -328,7 +330,7 @@ pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian)...@@ -328,7 +330,7 @@ pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian)
328 ///Create a PackedIntSlice of this slice using NewInt as the bit width integer330 ///Create a PackedIntSlice of this slice using NewInt as the bit width integer
329 /// and new_endian as the new endianess. NewInt's bit width must fit evenly within331 /// and new_endian as the new endianess. NewInt's bit width must fit evenly within
330 /// this slice's Int's total bits.332 /// this slice's Int's total bits.
331 pub fn sliceCastEndian(self: Self, comptime NewInt: type, comptime new_endian: builtin.Endian) PackedIntSliceEndian(NewInt, new_endian) {333 pub fn sliceCastEndian(self: Self, comptime NewInt: type, comptime new_endian: Endian) PackedIntSliceEndian(NewInt, new_endian) {
332 return Io.sliceCast(self.bytes, NewInt, new_endian, self.bit_offset, self.int_count);334 return Io.sliceCast(self.bytes, NewInt, new_endian, self.bit_offset, self.int_count);
333 }335 }
334 };336 };
...@@ -338,7 +340,7 @@ const we_are_testing_this_with_stage1_which_leaks_comptime_memory = true;...@@ -338,7 +340,7 @@ const we_are_testing_this_with_stage1_which_leaks_comptime_memory = true;
338340
339test "PackedIntArray" {341test "PackedIntArray" {
340 // TODO @setEvalBranchQuota generates panics in wasm32. Investigate.342 // TODO @setEvalBranchQuota generates panics in wasm32. Investigate.
341 if (builtin.arch == .wasm32) return error.SkipZigTest;343 if (builtin.target.cpu.arch == .wasm32) return error.SkipZigTest;
342 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;344 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
343345
344 @setEvalBranchQuota(10000);346 @setEvalBranchQuota(10000);
...@@ -348,7 +350,7 @@ test "PackedIntArray" {...@@ -348,7 +350,7 @@ test "PackedIntArray" {
348 comptime var bits = 0;350 comptime var bits = 0;
349 inline while (bits <= max_bits) : (bits += 1) {351 inline while (bits <= max_bits) : (bits += 1) {
350 //alternate unsigned and signed352 //alternate unsigned and signed
351 const sign: builtin.Signedness = if (bits % 2 == 0) .signed else .unsigned;353 const sign: std.builtin.Signedness = if (bits % 2 == 0) .signed else .unsigned;
352 const I = std.meta.Int(sign, bits);354 const I = std.meta.Int(sign, bits);
353355
354 const PackedArray = PackedIntArray(I, int_count);356 const PackedArray = PackedIntArray(I, int_count);
...@@ -394,7 +396,7 @@ test "PackedIntArray initAllTo" {...@@ -394,7 +396,7 @@ test "PackedIntArray initAllTo" {
394396
395test "PackedIntSlice" {397test "PackedIntSlice" {
396 // TODO @setEvalBranchQuota generates panics in wasm32. Investigate.398 // TODO @setEvalBranchQuota generates panics in wasm32. Investigate.
397 if (builtin.arch == .wasm32) return error.SkipZigTest;399 if (builtin.target.cpu.arch == .wasm32) return error.SkipZigTest;
398 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;400 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
399401
400 @setEvalBranchQuota(10000);402 @setEvalBranchQuota(10000);
...@@ -408,7 +410,7 @@ test "PackedIntSlice" {...@@ -408,7 +410,7 @@ test "PackedIntSlice" {
408 comptime var bits = 0;410 comptime var bits = 0;
409 inline while (bits <= max_bits) : (bits += 1) {411 inline while (bits <= max_bits) : (bits += 1) {
410 //alternate unsigned and signed412 //alternate unsigned and signed
411 const sign: builtin.Signedness = if (bits % 2 == 0) .signed else .unsigned;413 const sign: std.builtin.Signedness = if (bits % 2 == 0) .signed else .unsigned;
412 const I = std.meta.Int(sign, bits);414 const I = std.meta.Int(sign, bits);
413 const P = PackedIntSlice(I);415 const P = PackedIntSlice(I);
414416
...@@ -539,7 +541,7 @@ test "PackedInt(Array/Slice) sliceCast" {...@@ -539,7 +541,7 @@ test "PackedInt(Array/Slice) sliceCast" {
539541
540 var i = @as(usize, 0);542 var i = @as(usize, 0);
541 while (i < packed_slice_cast_2.len()) : (i += 1) {543 while (i < packed_slice_cast_2.len()) : (i += 1) {
542 const val = switch (builtin.endian) {544 const val = switch (native_endian) {
543 .Big => 0b01,545 .Big => 0b01,
544 .Little => 0b10,546 .Little => 0b10,
545 };547 };
...@@ -547,7 +549,7 @@ test "PackedInt(Array/Slice) sliceCast" {...@@ -547,7 +549,7 @@ test "PackedInt(Array/Slice) sliceCast" {
547 }549 }
548 i = 0;550 i = 0;
549 while (i < packed_slice_cast_4.len()) : (i += 1) {551 while (i < packed_slice_cast_4.len()) : (i += 1) {
550 const val = switch (builtin.endian) {552 const val = switch (native_endian) {
551 .Big => 0b0101,553 .Big => 0b0101,
552 .Little => 0b1010,554 .Little => 0b1010,
553 };555 };
...@@ -561,7 +563,7 @@ test "PackedInt(Array/Slice) sliceCast" {...@@ -561,7 +563,7 @@ test "PackedInt(Array/Slice) sliceCast" {
561 }563 }
562 i = 0;564 i = 0;
563 while (i < packed_slice_cast_3.len()) : (i += 1) {565 while (i < packed_slice_cast_3.len()) : (i += 1) {
564 const val = switch (builtin.endian) {566 const val = switch (native_endian) {
565 .Big => if (i % 2 == 0) @as(u3, 0b111) else @as(u3, 0b000),567 .Big => if (i % 2 == 0) @as(u3, 0b111) else @as(u3, 0b000),
566 .Little => if (i % 2 == 0) @as(u3, 0b111) else @as(u3, 0b000),568 .Little => if (i % 2 == 0) @as(u3, 0b111) else @as(u3, 0b000),
567 };569 };
...@@ -641,7 +643,7 @@ test "PackedInt(Array/Slice)Endian" {...@@ -641,7 +643,7 @@ test "PackedInt(Array/Slice)Endian" {
641test "PackedIntArray at end of available memory" {643test "PackedIntArray at end of available memory" {
642 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;644 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
643645
644 switch (builtin.os.tag) {646 switch (builtin.target.os.tag) {
645 .linux, .macos, .ios, .freebsd, .netbsd, .openbsd, .windows => {},647 .linux, .macos, .ios, .freebsd, .netbsd, .openbsd, .windows => {},
646 else => return,648 else => return,
647 }649 }
...@@ -662,7 +664,7 @@ test "PackedIntArray at end of available memory" {...@@ -662,7 +664,7 @@ test "PackedIntArray at end of available memory" {
662test "PackedIntSlice at end of available memory" {664test "PackedIntSlice at end of available memory" {
663 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;665 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
664666
665 switch (builtin.os.tag) {667 switch (builtin.target.os.tag) {
666 .linux, .macos, .ios, .freebsd, .netbsd, .openbsd, .windows => {},668 .linux, .macos, .ios, .freebsd, .netbsd, .openbsd, .windows => {},
667 else => return,669 else => return,
668 }670 }
lib/std/pdb.zig+3-3
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");6const builtin = std.builtin;
7const std = @import("std.zig");7const std = @import("std.zig");
8const io = std.io;8const io = std.io;
9const math = std.math;9const math = std.math;
...@@ -115,7 +115,7 @@ pub const StreamType = enum(u16) {...@@ -115,7 +115,7 @@ pub const StreamType = enum(u16) {
115115
116/// Duplicate copy of SymbolRecordKind, but using the official CV names. Useful116/// Duplicate copy of SymbolRecordKind, but using the official CV names. Useful
117/// for reference purposes and when dealing with unknown record types.117/// for reference purposes and when dealing with unknown record types.
118pub const SymbolKind = packed enum(u16) {118pub const SymbolKind = enum(u16) {
119 S_COMPILE = 1,119 S_COMPILE = 1,
120 S_REGISTER_16t = 2,120 S_REGISTER_16t = 2,
121 S_CONSTANT_16t = 3,121 S_CONSTANT_16t = 3,
...@@ -426,7 +426,7 @@ pub const FileChecksumEntryHeader = packed struct {...@@ -426,7 +426,7 @@ pub const FileChecksumEntryHeader = packed struct {
426 ChecksumKind: u8,426 ChecksumKind: u8,
427};427};
428428
429pub const DebugSubsectionKind = packed enum(u32) {429pub const DebugSubsectionKind = enum(u32) {
430 None = 0,430 None = 0,
431 Symbols = 0xf1,431 Symbols = 0xf1,
432 Lines = 0xf2,432 Lines = 0xf2,
lib/std/rand.zig+1-1
...@@ -13,7 +13,7 @@...@@ -13,7 +13,7 @@
13//! TODO(tiehuis): Benchmark these against other reference implementations.13//! TODO(tiehuis): Benchmark these against other reference implementations.
1414
15const std = @import("std.zig");15const std = @import("std.zig");
16const builtin = @import("builtin");16const builtin = std.builtin;
17const assert = std.debug.assert;17const assert = std.debug.assert;
18const expect = std.testing.expect;18const expect = std.testing.expect;
19const expectEqual = std.testing.expectEqual;19const expectEqual = std.testing.expectEqual;
lib/std/sort.zig+1-1
...@@ -8,7 +8,7 @@ const assert = std.debug.assert;...@@ -8,7 +8,7 @@ const assert = std.debug.assert;
8const testing = std.testing;8const testing = std.testing;
9const mem = std.mem;9const mem = std.mem;
10const math = std.math;10const math = std.math;
11const builtin = @import("builtin");11const builtin = std.builtin;
1212
13pub fn binarySearch(13pub fn binarySearch(
14 comptime T: type,14 comptime T: type,
lib/std/special/c.zig+10-7
...@@ -10,19 +10,22 @@...@@ -10,19 +10,22 @@
10// such as memcpy, memset, and some math functions.10// such as memcpy, memset, and some math functions.
1111
12const std = @import("std");12const std = @import("std");
13const builtin = @import("builtin");13const builtin = std.builtin;
14const maxInt = std.math.maxInt;14const maxInt = std.math.maxInt;
15const isNan = std.math.isNan;15const isNan = std.math.isNan;
16const native_arch = std.Target.current.cpu.arch;
17const native_abi = std.Target.current.abi;
18const native_os = std.Target.current.os.tag;
1619
17const is_wasm = switch (builtin.arch) {20const is_wasm = switch (native_arch) {
18 .wasm32, .wasm64 => true,21 .wasm32, .wasm64 => true,
19 else => false,22 else => false,
20};23};
21const is_msvc = switch (builtin.abi) {24const is_msvc = switch (native_abi) {
22 .msvc => true,25 .msvc => true,
23 else => false,26 else => false,
24};27};
25const is_freestanding = switch (builtin.os.tag) {28const is_freestanding = switch (native_os) {
26 .freestanding => true,29 .freestanding => true,
27 else => false,30 else => false,
28};31};
...@@ -174,7 +177,7 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn...@@ -174,7 +177,7 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
174 @setCold(true);177 @setCold(true);
175 std.debug.panic("{s}", .{msg});178 std.debug.panic("{s}", .{msg});
176 }179 }
177 if (builtin.os.tag != .freestanding and builtin.os.tag != .other) {180 if (native_os != .freestanding and native_os != .other) {
178 std.os.abort();181 std.os.abort();
179 }182 }
180 while (true) {}183 while (true) {}
...@@ -275,7 +278,7 @@ test "bcmp" {...@@ -275,7 +278,7 @@ test "bcmp" {
275}278}
276279
277comptime {280comptime {
278 if (builtin.os.tag == .linux) {281 if (native_os == .linux) {
279 @export(clone, .{ .name = "clone" });282 @export(clone, .{ .name = "clone" });
280 }283 }
281}284}
...@@ -284,7 +287,7 @@ comptime {...@@ -284,7 +287,7 @@ comptime {
284// it causes a segfault in release mode. this is a workaround of calling it287// it causes a segfault in release mode. this is a workaround of calling it
285// across .o file boundaries. fix comptime @ptrCast of nakedcc functions.288// across .o file boundaries. fix comptime @ptrCast of nakedcc functions.
286fn clone() callconv(.Naked) void {289fn clone() callconv(.Naked) void {
287 switch (builtin.arch) {290 switch (native_arch) {
288 .i386 => {291 .i386 => {
289 // __clone(func, stack, flags, arg, ptid, tls, ctid)292 // __clone(func, stack, flags, arg, ptid, tls, ctid)
290 // +8, +12, +16, +20, +24, +28, +32293 // +8, +12, +16, +20, +24, +28, +32
lib/std/special/compiler_rt.zig+13-10
...@@ -6,15 +6,18 @@...@@ -6,15 +6,18 @@
6const std = @import("std");6const std = @import("std");
7const builtin = std.builtin;7const builtin = std.builtin;
8const is_test = builtin.is_test;8const is_test = builtin.is_test;
9const os_tag = std.Target.current.os.tag;
10const arch = std.Target.current.cpu.arch;
11const abi = std.Target.current.abi;
912
10const is_gnu = std.Target.current.abi.isGnu();13const is_gnu = abi.isGnu();
11const is_mingw = builtin.os.tag == .windows and is_gnu;14const is_mingw = os_tag == .windows and is_gnu;
1215
13comptime {16comptime {
14 const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak;17 const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak;
15 const strong_linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong;18 const strong_linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong;
1619
17 switch (builtin.arch) {20 switch (arch) {
18 .i386,21 .i386,
19 .x86_64,22 .x86_64,
20 => @export(@import("compiler_rt/stack_probe.zig").zig_probe_stack, .{23 => @export(@import("compiler_rt/stack_probe.zig").zig_probe_stack, .{
...@@ -169,11 +172,11 @@ comptime {...@@ -169,11 +172,11 @@ comptime {
169172
170 @export(@import("compiler_rt/clzsi2.zig").__clzsi2, .{ .name = "__clzsi2", .linkage = linkage });173 @export(@import("compiler_rt/clzsi2.zig").__clzsi2, .{ .name = "__clzsi2", .linkage = linkage });
171174
172 if (builtin.link_libc and builtin.os.tag == .openbsd) {175 if (builtin.link_libc and os_tag == .openbsd) {
173 @export(@import("compiler_rt/emutls.zig").__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = linkage });176 @export(@import("compiler_rt/emutls.zig").__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = linkage });
174 }177 }
175178
176 if ((builtin.arch.isARM() or builtin.arch.isThumb()) and !is_test) {179 if ((arch.isARM() or arch.isThumb()) and !is_test) {
177 @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage });180 @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage });
178 @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage });181 @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage });
179 @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage });182 @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage });
...@@ -204,7 +207,7 @@ comptime {...@@ -204,7 +207,7 @@ comptime {
204 @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage });207 @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage });
205 @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage });208 @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage });
206209
207 if (builtin.os.tag == .linux) {210 if (os_tag == .linux) {
208 @export(@import("compiler_rt/arm.zig").__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage });211 @export(@import("compiler_rt/arm.zig").__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage });
209 }212 }
210213
...@@ -271,7 +274,7 @@ comptime {...@@ -271,7 +274,7 @@ comptime {
271 @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage });274 @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage });
272 }275 }
273276
274 if (builtin.arch == .i386 and builtin.abi == .msvc) {277 if (arch == .i386 and abi == .msvc) {
275 // Don't let LLVM apply the stdcall name mangling on those MSVC builtins278 // Don't let LLVM apply the stdcall name mangling on those MSVC builtins
276 @export(@import("compiler_rt/aulldiv.zig")._alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage });279 @export(@import("compiler_rt/aulldiv.zig")._alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage });
277 @export(@import("compiler_rt/aulldiv.zig")._aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage });280 @export(@import("compiler_rt/aulldiv.zig")._aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage });
...@@ -279,7 +282,7 @@ comptime {...@@ -279,7 +282,7 @@ comptime {
279 @export(@import("compiler_rt/aullrem.zig")._aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage });282 @export(@import("compiler_rt/aullrem.zig")._aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage });
280 }283 }
281284
282 if (builtin.arch.isSPARC()) {285 if (arch.isSPARC()) {
283 // SPARC systems use a different naming scheme286 // SPARC systems use a different naming scheme
284 @export(@import("compiler_rt/sparc.zig")._Qp_add, .{ .name = "_Qp_add", .linkage = linkage });287 @export(@import("compiler_rt/sparc.zig")._Qp_add, .{ .name = "_Qp_add", .linkage = linkage });
285 @export(@import("compiler_rt/sparc.zig")._Qp_div, .{ .name = "_Qp_div", .linkage = linkage });288 @export(@import("compiler_rt/sparc.zig")._Qp_div, .{ .name = "_Qp_div", .linkage = linkage });
...@@ -308,7 +311,7 @@ comptime {...@@ -308,7 +311,7 @@ comptime {
308 @export(@import("compiler_rt/sparc.zig")._Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage });311 @export(@import("compiler_rt/sparc.zig")._Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage });
309 }312 }
310313
311 if ((builtin.arch == .powerpc or builtin.arch.isPPC64()) and !is_test) {314 if ((arch == .powerpc or arch.isPPC64()) and !is_test) {
312 @export(@import("compiler_rt/addXf3.zig").__addtf3, .{ .name = "__addkf3", .linkage = linkage });315 @export(@import("compiler_rt/addXf3.zig").__addtf3, .{ .name = "__addkf3", .linkage = linkage });
313 @export(@import("compiler_rt/addXf3.zig").__subtf3, .{ .name = "__subkf3", .linkage = linkage });316 @export(@import("compiler_rt/addXf3.zig").__subtf3, .{ .name = "__subkf3", .linkage = linkage });
314 @export(@import("compiler_rt/mulXf3.zig").__multf3, .{ .name = "__mulkf3", .linkage = linkage });317 @export(@import("compiler_rt/mulXf3.zig").__multf3, .{ .name = "__mulkf3", .linkage = linkage });
...@@ -346,7 +349,7 @@ comptime {...@@ -346,7 +349,7 @@ comptime {
346 @export(@import("compiler_rt/stack_probe.zig").__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage });349 @export(@import("compiler_rt/stack_probe.zig").__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage });
347 }350 }
348351
349 switch (builtin.arch) {352 switch (arch) {
350 .i386 => {353 .i386 => {
351 @export(@import("compiler_rt/divti3.zig").__divti3, .{ .name = "__divti3", .linkage = linkage });354 @export(@import("compiler_rt/divti3.zig").__divti3, .{ .name = "__divti3", .linkage = linkage });
352 @export(@import("compiler_rt/modti3.zig").__modti3, .{ .name = "__modti3", .linkage = linkage });355 @export(@import("compiler_rt/modti3.zig").__modti3, .{ .name = "__modti3", .linkage = linkage });
lib/std/special/compiler_rt/atomics.zig+3-2
...@@ -5,6 +5,7 @@...@@ -5,6 +5,7 @@
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const builtin = std.builtin;7const builtin = std.builtin;
8const arch = std.Target.current.cpu.arch;
89
9const linkage: builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;10const linkage: builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
1011
...@@ -13,7 +14,7 @@ const linkage: builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak...@@ -13,7 +14,7 @@ const linkage: builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak
13// Some architectures support atomic load/stores but no CAS, but we ignore this14// Some architectures support atomic load/stores but no CAS, but we ignore this
14// detail to keep the export logic clean and because we need some kind of CAS to15// detail to keep the export logic clean and because we need some kind of CAS to
15// implement the spinlocks.16// implement the spinlocks.
16const supports_atomic_ops = switch (builtin.arch) {17const supports_atomic_ops = switch (arch) {
17 .msp430, .avr => false,18 .msp430, .avr => false,
18 .arm, .armeb, .thumb, .thumbeb =>19 .arm, .armeb, .thumb, .thumbeb =>
19 // The ARM v6m ISA has no ldrex/strex and so it's impossible to do CAS20 // The ARM v6m ISA has no ldrex/strex and so it's impossible to do CAS
...@@ -27,7 +28,7 @@ const supports_atomic_ops = switch (builtin.arch) {...@@ -27,7 +28,7 @@ const supports_atomic_ops = switch (builtin.arch) {
27// The size (in bytes) of the biggest object that the architecture can28// The size (in bytes) of the biggest object that the architecture can
28// load/store atomically.29// load/store atomically.
29// Objects bigger than this threshold require the use of a lock.30// Objects bigger than this threshold require the use of a lock.
30const largest_atomic_size = switch (builtin.arch) {31const largest_atomic_size = switch (arch) {
31 // XXX: On x86/x86_64 we could check the presence of cmpxchg8b/cmpxchg16b32 // XXX: On x86/x86_64 we could check the presence of cmpxchg8b/cmpxchg16b
32 // and set this parameter accordingly.33 // and set this parameter accordingly.
33 else => @sizeOf(usize),34 else => @sizeOf(usize),
lib/std/special/compiler_rt/compareXf2.zig+7-5
...@@ -10,18 +10,20 @@...@@ -10,18 +10,20 @@
10const std = @import("std");10const std = @import("std");
11const builtin = @import("builtin");11const builtin = @import("builtin");
1212
13const LE = extern enum(i32) {13const LE = enum(i32) {
14 Less = -1,14 Less = -1,
15 Equal = 0,15 Equal = 0,
16 Greater = 1,16 Greater = 1,
17 Unordered = 1,17
18 const Unordered: LE = .Greater;
18};19};
1920
20const GE = extern enum(i32) {21const GE = enum(i32) {
21 Less = -1,22 Less = -1,
22 Equal = 0,23 Equal = 0,
23 Greater = 1,24 Greater = 1,
24 Unordered = -1,25
26 const Unordered: GE = .Less;
25};27};
2628
27pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT {29pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT {
...@@ -43,7 +45,7 @@ pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT {...@@ -43,7 +45,7 @@ pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT {
43 const bAbs = @bitCast(rep_t, bInt) & absMask;45 const bAbs = @bitCast(rep_t, bInt) & absMask;
4446
45 // If either a or b is NaN, they are unordered.47 // If either a or b is NaN, they are unordered.
46 if (aAbs > infRep or bAbs > infRep) return .Unordered;48 if (aAbs > infRep or bAbs > infRep) return RT.Unordered;
4749
48 // If a and b are both zeros, they are equal.50 // If a and b are both zeros, they are equal.
49 if ((aAbs | bAbs) == 0) return .Equal;51 if ((aAbs | bAbs) == 0) return .Equal;
lib/std/special/compiler_rt/extendXfYf2_test.zig+1-1
...@@ -96,7 +96,7 @@ test "extendhfsf2" {...@@ -96,7 +96,7 @@ test "extendhfsf2" {
96 try test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN96 try test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN
97 // On x86 the NaN becomes quiet because the return is pushed on the x8797 // On x86 the NaN becomes quiet because the return is pushed on the x87
98 // stack due to ABI requirements98 // stack due to ABI requirements
99 if (builtin.arch != .i386 and builtin.os.tag == .windows)99 if (builtin.target.cpu.arch != .i386 and builtin.target.os.tag == .windows)
100 try test__extendhfsf2(0x7c01, 0x7f802000); // sNaN100 try test__extendhfsf2(0x7c01, 0x7f802000); // sNaN
101101
102 try test__extendhfsf2(0, 0); // 0102 try test__extendhfsf2(0, 0); // 0
lib/std/special/compiler_rt/muldi3.zig+6-4
...@@ -3,14 +3,16 @@...@@ -3,14 +3,16 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");6const std = @import("std");
7const is_test = std.builtin.is_test;
8const native_endian = std.Target.current.cpu.arch.endian();
79
8// Ported from10// Ported from
9// https://github.com/llvm/llvm-project/blob/llvmorg-9.0.0/compiler-rt/lib/builtins/muldi3.c11// https://github.com/llvm/llvm-project/blob/llvmorg-9.0.0/compiler-rt/lib/builtins/muldi3.c
1012
11const dwords = extern union {13const dwords = extern union {
12 all: i64,14 all: i64,
13 s: switch (builtin.endian) {15 s: switch (native_endian) {
14 .Little => extern struct {16 .Little => extern struct {
15 low: u32,17 low: u32,
16 high: u32,18 high: u32,
...@@ -23,7 +25,7 @@ const dwords = extern union {...@@ -23,7 +25,7 @@ const dwords = extern union {
23};25};
2426
25fn __muldsi3(a: u32, b: u32) i64 {27fn __muldsi3(a: u32, b: u32) i64 {
26 @setRuntimeSafety(builtin.is_test);28 @setRuntimeSafety(is_test);
2729
28 const bits_in_word_2 = @sizeOf(i32) * 8 / 2;30 const bits_in_word_2 = @sizeOf(i32) * 8 / 2;
29 const lower_mask = (~@as(u32, 0)) >> bits_in_word_2;31 const lower_mask = (~@as(u32, 0)) >> bits_in_word_2;
...@@ -45,7 +47,7 @@ fn __muldsi3(a: u32, b: u32) i64 {...@@ -45,7 +47,7 @@ fn __muldsi3(a: u32, b: u32) i64 {
45}47}
4648
47pub fn __muldi3(a: i64, b: i64) callconv(.C) i64 {49pub fn __muldi3(a: i64, b: i64) callconv(.C) i64 {
48 @setRuntimeSafety(builtin.is_test);50 @setRuntimeSafety(is_test);
4951
50 const x = dwords{ .all = a };52 const x = dwords{ .all = a };
51 const y = dwords{ .all = b };53 const y = dwords{ .all = b };
lib/std/special/compiler_rt/multi3.zig+5-3
...@@ -3,15 +3,17 @@...@@ -3,15 +3,17 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");
7const compiler_rt = @import("../compiler_rt.zig");6const compiler_rt = @import("../compiler_rt.zig");
7const std = @import("std");
8const is_test = std.builtin.is_test;
9const native_endian = std.Target.current.cpu.arch.endian();
810
9// Ported from git@github.com:llvm-project/llvm-project-20170507.git11// Ported from git@github.com:llvm-project/llvm-project-20170507.git
10// ae684fad6d34858c014c94da69c15e7774a633c312// ae684fad6d34858c014c94da69c15e7774a633c3
11// 2018-08-1313// 2018-08-13
1214
13pub fn __multi3(a: i128, b: i128) callconv(.C) i128 {15pub fn __multi3(a: i128, b: i128) callconv(.C) i128 {
14 @setRuntimeSafety(builtin.is_test);16 @setRuntimeSafety(is_test);
15 const x = twords{ .all = a };17 const x = twords{ .all = a };
16 const y = twords{ .all = b };18 const y = twords{ .all = b };
17 var r = twords{ .all = __mulddi3(x.s.low, y.s.low) };19 var r = twords{ .all = __mulddi3(x.s.low, y.s.low) };
...@@ -50,7 +52,7 @@ const twords = extern union {...@@ -50,7 +52,7 @@ const twords = extern union {
50 all: i128,52 all: i128,
51 s: S,53 s: S,
5254
53 const S = if (builtin.endian == .Little)55 const S = if (native_endian == .Little)
54 struct {56 struct {
55 low: u64,57 low: u64,
56 high: u64,58 high: u64,
lib/std/special/compiler_rt/shift.zig+2-2
...@@ -4,8 +4,8 @@...@@ -4,8 +4,8 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const builtin = std.builtin;
8const Log2Int = std.math.Log2Int;7const Log2Int = std.math.Log2Int;
8const native_endian = std.Target.current.cpu.arch.endian();
99
10fn Dwords(comptime T: type, comptime signed_half: bool) type {10fn Dwords(comptime T: type, comptime signed_half: bool) type {
11 return extern union {11 return extern union {
...@@ -15,7 +15,7 @@ fn Dwords(comptime T: type, comptime signed_half: bool) type {...@@ -15,7 +15,7 @@ fn Dwords(comptime T: type, comptime signed_half: bool) type {
15 pub const HalfT = if (signed_half) HalfTS else HalfTU;15 pub const HalfT = if (signed_half) HalfTS else HalfTU;
1616
17 all: T,17 all: T,
18 s: if (builtin.endian == .Little)18 s: if (native_endian == .Little)
19 struct { low: HalfT, high: HalfT }19 struct { low: HalfT, high: HalfT }
20 else20 else
21 struct { high: HalfT, low: HalfT },21 struct { high: HalfT, low: HalfT },
lib/std/special/compiler_rt/sparc.zig+1-1
...@@ -11,7 +11,7 @@ const builtin = @import("builtin");...@@ -11,7 +11,7 @@ const builtin = @import("builtin");
1111
12// The SPARC Architecture Manual, Version 9:12// The SPARC Architecture Manual, Version 9:
13// A.13 Floating-Point Compare13// A.13 Floating-Point Compare
14const FCMP = extern enum(i32) {14const FCMP = enum(i32) {
15 Equal = 0,15 Equal = 0,
16 Less = 1,16 Less = 1,
17 Greater = 2,17 Greater = 2,
lib/std/special/compiler_rt/stack_probe.zig+5-5
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");6const native_arch = @import("std").Target.current.cpu.arch;
77
8// Zig's own stack-probe routine (available only on x86 and x86_64)8// Zig's own stack-probe routine (available only on x86 and x86_64)
9pub fn zig_probe_stack() callconv(.Naked) void {9pub fn zig_probe_stack() callconv(.Naked) void {
...@@ -13,7 +13,7 @@ pub fn zig_probe_stack() callconv(.Naked) void {...@@ -13,7 +13,7 @@ pub fn zig_probe_stack() callconv(.Naked) void {
13 // invalid so let's update it on the go, otherwise we'll get a segfault13 // invalid so let's update it on the go, otherwise we'll get a segfault
14 // instead of triggering the stack growth.14 // instead of triggering the stack growth.
1515
16 switch (builtin.arch) {16 switch (native_arch) {
17 .x86_64 => {17 .x86_64 => {
18 // %rax = probe length, %rsp = stack pointer18 // %rax = probe length, %rsp = stack pointer
19 asm volatile (19 asm volatile (
...@@ -65,7 +65,7 @@ pub fn zig_probe_stack() callconv(.Naked) void {...@@ -65,7 +65,7 @@ pub fn zig_probe_stack() callconv(.Naked) void {
65fn win_probe_stack_only() void {65fn win_probe_stack_only() void {
66 @setRuntimeSafety(false);66 @setRuntimeSafety(false);
6767
68 switch (builtin.arch) {68 switch (native_arch) {
69 .x86_64 => {69 .x86_64 => {
70 asm volatile (70 asm volatile (
71 \\ push %%rcx71 \\ push %%rcx
...@@ -117,7 +117,7 @@ fn win_probe_stack_only() void {...@@ -117,7 +117,7 @@ fn win_probe_stack_only() void {
117fn win_probe_stack_adjust_sp() void {117fn win_probe_stack_adjust_sp() void {
118 @setRuntimeSafety(false);118 @setRuntimeSafety(false);
119119
120 switch (builtin.arch) {120 switch (native_arch) {
121 .x86_64 => {121 .x86_64 => {
122 asm volatile (122 asm volatile (
123 \\ push %%rcx123 \\ push %%rcx
...@@ -191,7 +191,7 @@ pub fn _chkstk() callconv(.Naked) void {...@@ -191,7 +191,7 @@ pub fn _chkstk() callconv(.Naked) void {
191}191}
192pub fn __chkstk() callconv(.Naked) void {192pub fn __chkstk() callconv(.Naked) void {
193 @setRuntimeSafety(false);193 @setRuntimeSafety(false);
194 switch (builtin.arch) {194 switch (native_arch) {
195 .i386 => @call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{}),195 .i386 => @call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{}),
196 .x86_64 => @call(.{ .modifier = .always_inline }, win_probe_stack_only, .{}),196 .x86_64 => @call(.{ .modifier = .always_inline }, win_probe_stack_only, .{}),
197 else => unreachable,197 else => unreachable,
lib/std/special/compiler_rt/udivmod.zig+2-1
...@@ -5,8 +5,9 @@...@@ -5,8 +5,9 @@
5// and substantial portions of the software.5// and substantial portions of the software.
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const is_test = builtin.is_test;7const is_test = builtin.is_test;
8const native_endian = @import("std").Target.current.cpu.arch.endian();
89
9const low = switch (builtin.endian) {10const low = switch (native_endian) {
10 .Big => 1,11 .Big => 1,
11 .Little => 0,12 .Little => 0,
12};13};
lib/std/special/test_runner.zig+10
...@@ -22,6 +22,9 @@ fn processArgs() void {...@@ -22,6 +22,9 @@ fn processArgs() void {
22}22}
2323
24pub fn main() anyerror!void {24pub fn main() anyerror!void {
25 if (builtin.zig_is_stage2) {
26 return main2();
27 }
25 processArgs();28 processArgs();
26 const test_fn_list = builtin.test_functions;29 const test_fn_list = builtin.test_functions;
27 var ok_count: usize = 0;30 var ok_count: usize = 0;
...@@ -123,3 +126,10 @@ pub fn log(...@@ -123,3 +126,10 @@ pub fn log(
123 std.debug.print("[{s}] ({s}): " ++ format ++ "\n", .{ @tagName(scope), @tagName(message_level) } ++ args);126 std.debug.print("[{s}] ({s}): " ++ format ++ "\n", .{ @tagName(scope), @tagName(message_level) } ++ args);
124 }127 }
125}128}
129
130pub fn main2() anyerror!void {
131 // Simpler main(), exercising fewer language features, so that stage2 can handle it.
132 for (builtin.test_functions) |test_fn| {
133 try test_fn.func();
134 }
135}
lib/std/start.zig+73-35
...@@ -11,30 +11,36 @@ const builtin = @import("builtin");...@@ -11,30 +11,36 @@ const builtin = @import("builtin");
11const assert = std.debug.assert;11const assert = std.debug.assert;
12const uefi = std.os.uefi;12const uefi = std.os.uefi;
13const tlcsprng = @import("crypto/tlcsprng.zig");13const tlcsprng = @import("crypto/tlcsprng.zig");
14const native_arch = builtin.cpu.arch;
15const native_os = builtin.os.tag;
1416
15var argc_argv_ptr: [*]usize = undefined;17var argc_argv_ptr: [*]usize = undefined;
1618
17const start_sym_name = if (builtin.arch.isMIPS()) "__start" else "_start";19const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start";
1820
19comptime {21comptime {
22 // No matter what, we import the root file, so that any export, test, comptime
23 // decls there get run.
24 _ = root;
25
20 // The self-hosted compiler is not fully capable of handling all of this start.zig file.26 // The self-hosted compiler is not fully capable of handling all of this start.zig file.
21 // Until then, we have simplified logic here for self-hosted. TODO remove this once27 // Until then, we have simplified logic here for self-hosted. TODO remove this once
22 // self-hosted is capable enough to handle all of the real start.zig logic.28 // self-hosted is capable enough to handle all of the real start.zig logic.
23 if (builtin.zig_is_stage2) {29 if (builtin.zig_is_stage2) {
24 if (builtin.output_mode == .Exe) {30 if (builtin.output_mode == .Exe) {
25 if (builtin.link_libc or builtin.object_format == .c) {31 if ((builtin.link_libc or builtin.object_format == .c) and @hasDecl(root, "main")) {
26 if (!@hasDecl(root, "main")) {32 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {
27 @export(main2, "main");33 @export(main2, .{ .name = "main" });
28 }34 }
29 } else {35 } else {
30 if (!@hasDecl(root, "_start")) {36 if (!@hasDecl(root, "_start")) {
31 @export(_start2, "_start");37 @export(_start2, .{ .name = "_start" });
32 }38 }
33 }39 }
34 }40 }
35 } else {41 } else {
36 if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) {42 if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) {
37 if (builtin.os.tag == .windows and !@hasDecl(root, "_DllMainCRTStartup")) {43 if (native_os == .windows and !@hasDecl(root, "_DllMainCRTStartup")) {
38 @export(_DllMainCRTStartup, .{ .name = "_DllMainCRTStartup" });44 @export(_DllMainCRTStartup, .{ .name = "_DllMainCRTStartup" });
39 }45 }
40 } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) {46 } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) {
...@@ -42,7 +48,7 @@ comptime {...@@ -42,7 +48,7 @@ comptime {
42 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {48 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {
43 @export(main, .{ .name = "main" });49 @export(main, .{ .name = "main" });
44 }50 }
45 } else if (builtin.os.tag == .windows) {51 } else if (native_os == .windows) {
46 if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and52 if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and
47 !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup"))53 !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup"))
48 {54 {
...@@ -56,11 +62,11 @@ comptime {...@@ -56,11 +62,11 @@ comptime {
56 {62 {
57 @export(wWinMainCRTStartup, .{ .name = "wWinMainCRTStartup" });63 @export(wWinMainCRTStartup, .{ .name = "wWinMainCRTStartup" });
58 }64 }
59 } else if (builtin.os.tag == .uefi) {65 } else if (native_os == .uefi) {
60 if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" });66 if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" });
61 } else if (builtin.arch.isWasm() and builtin.os.tag == .freestanding) {67 } else if (native_arch.isWasm() and native_os == .freestanding) {
62 if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name });68 if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name });
63 } else if (builtin.os.tag != .other and builtin.os.tag != .freestanding) {69 } else if (native_os != .other and native_os != .freestanding) {
64 if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name });70 if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name });
65 }71 }
66 }72 }
...@@ -79,8 +85,8 @@ fn _start2() callconv(.Naked) noreturn {...@@ -79,8 +85,8 @@ fn _start2() callconv(.Naked) noreturn {
79 exit2(0);85 exit2(0);
80}86}
8187
82fn exit2(code: u8) noreturn {88fn exit2(code: usize) noreturn {
83 switch (builtin.arch) {89 switch (builtin.stage2_arch) {
84 .x86_64 => {90 .x86_64 => {
85 asm volatile ("syscall"91 asm volatile ("syscall"
86 :92 :
...@@ -157,13 +163,13 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv...@@ -157,13 +163,13 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv
157}163}
158164
159fn _start() callconv(.Naked) noreturn {165fn _start() callconv(.Naked) noreturn {
160 if (builtin.os.tag == .wasi) {166 if (native_os == .wasi) {
161 // This is marked inline because for some reason LLVM in release mode fails to inline it,167 // This is marked inline because for some reason LLVM in release mode fails to inline it,
162 // and we want fewer call frames in stack traces.168 // and we want fewer call frames in stack traces.
163 std.os.wasi.proc_exit(@call(.{ .modifier = .always_inline }, callMain, .{}));169 std.os.wasi.proc_exit(@call(.{ .modifier = .always_inline }, callMain, .{}));
164 }170 }
165171
166 switch (builtin.arch) {172 switch (native_arch) {
167 .x86_64 => {173 .x86_64 => {
168 argc_argv_ptr = asm volatile (174 argc_argv_ptr = asm volatile (
169 \\ xor %%rbp, %%rbp175 \\ xor %%rbp, %%rbp
...@@ -273,7 +279,7 @@ fn posixCallMainAndExit() noreturn {...@@ -273,7 +279,7 @@ fn posixCallMainAndExit() noreturn {
273 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}279 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
274 const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];280 const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];
275281
276 if (builtin.os.tag == .linux) {282 if (native_os == .linux) {
277 // Find the beginning of the auxiliary vector283 // Find the beginning of the auxiliary vector
278 const auxv = @ptrCast([*]std.elf.Auxv, @alignCast(@alignOf(usize), envp.ptr + envp_count + 1));284 const auxv = @ptrCast([*]std.elf.Auxv, @alignCast(@alignOf(usize), envp.ptr + envp_count + 1));
279 std.os.linux.elf_aux_maybe = auxv;285 std.os.linux.elf_aux_maybe = auxv;
...@@ -291,31 +297,56 @@ fn posixCallMainAndExit() noreturn {...@@ -291,31 +297,56 @@ fn posixCallMainAndExit() noreturn {
291 std.os.linux.tls.initStaticTLS();297 std.os.linux.tls.initStaticTLS();
292 }298 }
293299
294 // TODO This is disabled because what should we do when linking libc and this code300 // Linux ignores the stack size from the ELF file, and instead always gives 8 MiB.
295 // does not execute? And also it's causing a test failure in stack traces in release modes.301 // Here we look for the stack size in our program headers and tell the kernel,
296302 // no, seriously, give me that stack space, I wasn't joking.
297 //// Linux ignores the stack size from the ELF file, and instead always does 8 MiB. A further303 {
298 //// problem is that it uses PROT_GROWSDOWN which prevents stores to addresses too far down304 var i: usize = 0;
299 //// the stack and requires "probing". So here we allocate our own stack.305 var at_phdr: usize = undefined;
300 //const wanted_stack_size = gnu_stack_phdr.p_memsz;306 var at_phnum: usize = undefined;
301 //assert(wanted_stack_size % std.mem.page_size == 0);307 while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
302 //// Allocate an extra page as the guard page.308 switch (auxv[i].a_type) {
303 //const total_size = wanted_stack_size + std.mem.page_size;309 std.elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
304 //const new_stack = std.os.mmap(310 std.elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val,
305 // null,311 else => continue,
306 // total_size,312 }
307 // std.os.PROT_READ | std.os.PROT_WRITE,313 }
308 // std.os.MAP_PRIVATE | std.os.MAP_ANONYMOUS,314 expandStackSize(at_phdr, at_phnum);
309 // -1,315 }
310 // 0,
311 //) catch @panic("out of memory");
312 //std.os.mprotect(new_stack[0..std.mem.page_size], std.os.PROT_NONE) catch {};
313 //std.os.exit(@call(.{.stack = new_stack}, callMainWithArgs, .{argc, argv, envp}));
314 }316 }
315317
316 std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));318 std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
317}319}
318320
321fn expandStackSize(at_phdr: usize, at_phnum: usize) void {
322 const phdrs = (@intToPtr([*]std.elf.Phdr, at_phdr))[0..at_phnum];
323 for (phdrs) |*phdr| {
324 switch (phdr.p_type) {
325 std.elf.PT_GNU_STACK => {
326 const wanted_stack_size = phdr.p_memsz;
327 assert(wanted_stack_size % std.mem.page_size == 0);
328
329 std.os.setrlimit(.STACK, .{
330 .cur = wanted_stack_size,
331 .max = wanted_stack_size,
332 }) catch {
333 // If this is a debug build, it will be useful to find out
334 // why this failed. If it is a release build, we allow the
335 // stack overflow to cause a segmentation fault. Memory safety
336 // is not compromised, however, depending on runtime state,
337 // the application may crash due to provided stack space not
338 // matching the known upper bound.
339 if (builtin.mode == .Debug) {
340 @panic("unable to increase stack size");
341 }
342 };
343 break;
344 },
345 else => {},
346 }
347 }
348}
349
319fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {350fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
320 std.os.argv = argv[0..argc];351 std.os.argv = argv[0..argc];
321 std.os.environ = envp;352 std.os.environ = envp;
...@@ -329,6 +360,13 @@ fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C)...@@ -329,6 +360,13 @@ fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C)
329 var env_count: usize = 0;360 var env_count: usize = 0;
330 while (c_envp[env_count] != null) : (env_count += 1) {}361 while (c_envp[env_count] != null) : (env_count += 1) {}
331 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];362 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];
363
364 if (builtin.os.tag == .linux) {
365 const at_phdr = std.c.getauxval(std.elf.AT_PHDR);
366 const at_phnum = std.c.getauxval(std.elf.AT_PHNUM);
367 expandStackSize(at_phdr, at_phnum);
368 }
369
332 return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });370 return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
333}371}
334372
lib/std/start_windows_tls.zig+2-2
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const builtin = std.builtin;7const builtin = @import("builtin");
88
9export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES;9export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES;
10export var _tls_start: u8 linksection(".tls") = 0;10export var _tls_start: u8 linksection(".tls") = 0;
...@@ -13,7 +13,7 @@ export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") =...@@ -13,7 +13,7 @@ export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") =
13export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null;13export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null;
1414
15comptime {15comptime {
16 if (builtin.arch == .i386) {16 if (builtin.target.cpu.arch == .i386) {
17 // The __tls_array is the offset of the ThreadLocalStoragePointer field17 // The __tls_array is the offset of the ThreadLocalStoragePointer field
18 // in the TEB block whose base address held in the %fs segment.18 // in the TEB block whose base address held in the %fs segment.
19 asm (19 asm (
lib/std/target.zig+1-5
...@@ -1242,11 +1242,7 @@ pub const Target = struct {...@@ -1242,11 +1242,7 @@ pub const Target = struct {
1242 }1242 }
1243 };1243 };
12441244
1245 pub const current = Target{1245 pub const current = builtin.target;
1246 .cpu = builtin.cpu,
1247 .os = builtin.os,
1248 .abi = builtin.abi,
1249 };
12501246
1251 pub const stack_align = 16;1247 pub const stack_align = 16;
12521248
lib/std/testing.zig+1-1
...@@ -327,7 +327,7 @@ pub const TmpDir = struct {...@@ -327,7 +327,7 @@ pub const TmpDir = struct {
327};327};
328328
329fn getCwdOrWasiPreopen() std.fs.Dir {329fn getCwdOrWasiPreopen() std.fs.Dir {
330 if (@import("builtin").os.tag == .wasi) {330 if (std.builtin.os.tag == .wasi) {
331 var preopens = std.fs.wasi.PreopenList.init(allocator);331 var preopens = std.fs.wasi.PreopenList.init(allocator);
332 defer preopens.deinit();332 defer preopens.deinit();
333 preopens.populate() catch333 preopens.populate() catch
lib/std/unicode.zig+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("./std.zig");6const std = @import("./std.zig");
7const builtin = @import("builtin");7const builtin = std.builtin;
8const assert = std.debug.assert;8const assert = std.debug.assert;
9const testing = std.testing;9const testing = std.testing;
10const mem = std.mem;10const mem = std.mem;
lib/std/valgrind.zig+5-5
...@@ -12,7 +12,7 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:...@@ -12,7 +12,7 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:
12 return default;12 return default;
13 }13 }
1414
15 switch (builtin.arch) {15 switch (builtin.target.cpu.arch) {
16 .i386 => {16 .i386 => {
17 return asm volatile (17 return asm volatile (
18 \\ roll $3, %%edi ; roll $13, %%edi18 \\ roll $3, %%edi ; roll $13, %%edi
...@@ -48,7 +48,7 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:...@@ -48,7 +48,7 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:
48 }48 }
49}49}
5050
51pub const ClientRequest = extern enum {51pub const ClientRequest = enum(u32) {
52 RunningOnValgrind = 4097,52 RunningOnValgrind = 4097,
53 DiscardTranslations = 4098,53 DiscardTranslations = 4098,
54 ClientCall0 = 4353,54 ClientCall0 = 4353,
...@@ -156,9 +156,9 @@ pub fn freeLikeBlock(addr: [*]u8, rzB: usize) void {...@@ -156,9 +156,9 @@ pub fn freeLikeBlock(addr: [*]u8, rzB: usize) void {
156}156}
157157
158/// Create a memory pool.158/// Create a memory pool.
159pub const MempoolFlags = extern enum {159pub const MempoolFlags = struct {
160 AutoFree = 1,160 pub const AutoFree = 1;
161 MetaPool = 2,161 pub const MetaPool = 2;
162};162};
163pub fn createMempool(pool: [*]u8, rzB: usize, is_zeroed: bool, flags: usize) void {163pub fn createMempool(pool: [*]u8, rzB: usize, is_zeroed: bool, flags: usize) void {
164 doClientRequestStmt(.CreateMempool, @ptrToInt(pool), rzB, @boolToInt(is_zeroed), flags, 0);164 doClientRequestStmt(.CreateMempool, @ptrToInt(pool), rzB, @boolToInt(is_zeroed), flags, 0);
lib/std/valgrind/callgrind.zig+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const valgrind = std.valgrind;7const valgrind = std.valgrind;
88
9pub const CallgrindClientRequest = extern enum {9pub const CallgrindClientRequest = enum(usize) {
10 DumpStats = valgrind.ToolBase("CT"),10 DumpStats = valgrind.ToolBase("CT"),
11 ZeroStats,11 ZeroStats,
12 ToggleCollect,12 ToggleCollect,
lib/std/valgrind/memcheck.zig+2-2
...@@ -7,7 +7,7 @@ const std = @import("../std.zig");...@@ -7,7 +7,7 @@ const std = @import("../std.zig");
7const testing = std.testing;7const testing = std.testing;
8const valgrind = std.valgrind;8const valgrind = std.valgrind;
99
10pub const MemCheckClientRequest = extern enum {10pub const MemCheckClientRequest = enum(usize) {
11 MakeMemNoAccess = valgrind.ToolBase("MC".*),11 MakeMemNoAccess = valgrind.ToolBase("MC".*),
12 MakeMemUndefined,12 MakeMemUndefined,
13 MakeMemDefined,13 MakeMemDefined,
...@@ -76,7 +76,7 @@ pub fn createBlock(qzz: []u8, desc: [*]u8) usize {...@@ -76,7 +76,7 @@ pub fn createBlock(qzz: []u8, desc: [*]u8) usize {
7676
77/// Discard a block-description-handle. Returns 1 for an77/// Discard a block-description-handle. Returns 1 for an
78/// invalid handle, 0 for a valid handle.78/// invalid handle, 0 for a valid handle.
79pub fn discard(blkindex) bool {79pub fn discard(blkindex: usize) bool {
80 return doMemCheckClientRequestExpr(0, // default return80 return doMemCheckClientRequestExpr(0, // default return
81 .Discard, 0, blkindex, 0, 0, 0) != 0;81 .Discard, 0, blkindex, 0, 0, 0) != 0;
82}82}
lib/std/x/net/tcp.zig+1-1
...@@ -50,7 +50,7 @@ pub const Connection = struct {...@@ -50,7 +50,7 @@ pub const Connection = struct {
50};50};
5151
52/// Possible domains that a TCP client/listener may operate over.52/// Possible domains that a TCP client/listener may operate over.
53pub const Domain = extern enum(u16) {53pub const Domain = enum(u16) {
54 ip = os.AF_INET,54 ip = os.AF_INET,
55 ipv6 = os.AF_INET6,55 ipv6 = os.AF_INET6,
56};56};
lib/std/x/os/net.zig+1-1
...@@ -352,7 +352,7 @@ pub const IPv6 = extern struct {...@@ -352,7 +352,7 @@ pub const IPv6 = extern struct {
352 opts: fmt.FormatOptions,352 opts: fmt.FormatOptions,
353 writer: anytype,353 writer: anytype,
354 ) !void {354 ) !void {
355 comptime const specifier = &[_]u8{if (layout.len == 0) 'x' else switch (layout[0]) {355 const specifier = comptime &[_]u8{if (layout.len == 0) 'x' else switch (layout[0]) {
356 'x', 'X' => |specifier| specifier,356 'x', 'X' => |specifier| specifier,
357 's' => 'x',357 's' => 'x',
358 'S' => 'X',358 'S' => 'X',
lib/std/zig.zig+4
...@@ -24,6 +24,10 @@ pub fn hashSrc(src: []const u8) SrcHash {...@@ -24,6 +24,10 @@ pub fn hashSrc(src: []const u8) SrcHash {
24 return out;24 return out;
25}25}
2626
27pub fn srcHashEql(a: SrcHash, b: SrcHash) bool {
28 return @bitCast(u128, a) == @bitCast(u128, b);
29}
30
27pub fn hashName(parent_hash: SrcHash, sep: []const u8, name: []const u8) SrcHash {31pub fn hashName(parent_hash: SrcHash, sep: []const u8, name: []const u8) SrcHash {
28 var out: SrcHash = undefined;32 var out: SrcHash = undefined;
29 var hasher = std.crypto.hash.Blake3.init(.{});33 var hasher = std.crypto.hash.Blake3.init(.{});
lib/std/zig/ast.zig+7-6
...@@ -2178,6 +2178,10 @@ pub const full = struct {...@@ -2178,6 +2178,10 @@ pub const full = struct {
2178 };2178 };
2179 it.param_i += 1;2179 it.param_i += 1;
2180 it.tok_i = it.tree.lastToken(param_type) + 1;2180 it.tok_i = it.tree.lastToken(param_type) + 1;
2181 // Look for anytype and ... params afterwards.
2182 if (token_tags[it.tok_i] == .comma) {
2183 it.tok_i += 1;
2184 }
2181 it.tok_flag = true;2185 it.tok_flag = true;
2182 return Param{2186 return Param{
2183 .first_doc_comment = first_doc_comment,2187 .first_doc_comment = first_doc_comment,
...@@ -2187,10 +2191,7 @@ pub const full = struct {...@@ -2187,10 +2191,7 @@ pub const full = struct {
2187 .type_expr = param_type,2191 .type_expr = param_type,
2188 };2192 };
2189 }2193 }
2190 // Look for anytype and ... params afterwards.2194 if (token_tags[it.tok_i] == .r_paren) {
2191 if (token_tags[it.tok_i] == .comma) {
2192 it.tok_i += 1;
2193 } else {
2194 return null;2195 return null;
2195 }2196 }
2196 if (token_tags[it.tok_i] == .doc_comment) {2197 if (token_tags[it.tok_i] == .doc_comment) {
...@@ -2242,8 +2243,8 @@ pub const full = struct {...@@ -2242,8 +2243,8 @@ pub const full = struct {
2242 .tree = &tree,2243 .tree = &tree,
2243 .fn_proto = &fn_proto,2244 .fn_proto = &fn_proto,
2244 .param_i = 0,2245 .param_i = 0,
2245 .tok_i = undefined,2246 .tok_i = fn_proto.lparen + 1,
2246 .tok_flag = false,2247 .tok_flag = true,
2247 };2248 };
2248 }2249 }
2249 };2250 };
lib/std/zig/render.zig-1
...@@ -1595,7 +1595,6 @@ fn renderStructInit(...@@ -1595,7 +1595,6 @@ fn renderStructInit(
1595 return renderToken(ais, tree, rbrace, space);1595 return renderToken(ais, tree, rbrace, space);
1596}1596}
15971597
1598// TODO: handle comments between elements
1599fn renderArrayInit(1598fn renderArrayInit(
1600 gpa: *Allocator,1599 gpa: *Allocator,
1601 ais: *Ais,1600 ais: *Ais,
lib/std/zig/system.zig+2-1
...@@ -14,6 +14,7 @@ const process = std.process;...@@ -14,6 +14,7 @@ const process = std.process;
14const Target = std.Target;14const Target = std.Target;
15const CrossTarget = std.zig.CrossTarget;15const CrossTarget = std.zig.CrossTarget;
16const macos = @import("system/macos.zig");16const macos = @import("system/macos.zig");
17const native_endian = std.Target.current.cpu.arch.endian();
17const linux = @import("system/linux.zig");18const linux = @import("system/linux.zig");
18pub const windows = @import("system/windows.zig");19pub const windows = @import("system/windows.zig");
1920
...@@ -662,7 +663,7 @@ pub const NativeTargetInfo = struct {...@@ -662,7 +663,7 @@ pub const NativeTargetInfo = struct {
662 elf.ELFDATA2MSB => .Big,663 elf.ELFDATA2MSB => .Big,
663 else => return error.InvalidElfEndian,664 else => return error.InvalidElfEndian,
664 };665 };
665 const need_bswap = elf_endian != std.builtin.endian;666 const need_bswap = elf_endian != native_endian;
666 if (hdr32.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion;667 if (hdr32.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion;
667668
668 const is_64 = switch (hdr32.e_ident[elf.EI_CLASS]) {669 const is_64 = switch (hdr32.e_ident[elf.EI_CLASS]) {
src/AstGen.zig+7876-3488
...@@ -1,8 +1,4 @@...@@ -1,8 +1,4 @@
1//! A Work-In-Progress `zir.Code`. This is a shared parent of all1//! Ingests an AST and produces ZIR code.
2//! `GenZir` scopes. Once the `zir.Code` is produced, this struct
3//! is deinitialized.
4//! The `GenZir.finish` function converts this to a `zir.Code`.
5
6const AstGen = @This();2const AstGen = @This();
73
8const std = @import("std");4const std = @import("std");
...@@ -12,102 +8,160 @@ const Allocator = std.mem.Allocator;...@@ -12,102 +8,160 @@ const Allocator = std.mem.Allocator;
12const assert = std.debug.assert;8const assert = std.debug.assert;
13const ArrayListUnmanaged = std.ArrayListUnmanaged;9const ArrayListUnmanaged = std.ArrayListUnmanaged;
1410
15const Value = @import("value.zig").Value;11const Zir = @import("Zir.zig");
16const Type = @import("type.zig").Type;
17const TypedValue = @import("TypedValue.zig");
18const zir = @import("zir.zig");
19const Module = @import("Module.zig");
20const trace = @import("tracy.zig").trace;12const trace = @import("tracy.zig").trace;
21const Scope = Module.Scope;
22const GenZir = Scope.GenZir;
23const InnerError = Module.InnerError;
24const Decl = Module.Decl;
25const LazySrcLoc = Module.LazySrcLoc;
26const BuiltinFn = @import("BuiltinFn.zig");13const BuiltinFn = @import("BuiltinFn.zig");
2714
28instructions: std.MultiArrayList(zir.Inst) = .{},15gpa: *Allocator,
29string_bytes: ArrayListUnmanaged(u8) = .{},16tree: *const ast.Tree,
17instructions: std.MultiArrayList(Zir.Inst) = .{},
30extra: ArrayListUnmanaged(u32) = .{},18extra: ArrayListUnmanaged(u32) = .{},
31/// The end of special indexes. `zir.Inst.Ref` subtracts against this number to convert19string_bytes: ArrayListUnmanaged(u8) = .{},
32/// to `zir.Inst.Index`. The default here is correct if there are 0 parameters.20/// Used for temporary allocations; freed after AstGen is complete.
33ref_start_index: u32 = zir.Inst.Ref.typed_value_map.len,21/// The resulting ZIR code has no references to anything in this arena.
34mod: *Module,
35decl: *Decl,
36arena: *Allocator,22arena: *Allocator,
23string_table: std.StringHashMapUnmanaged(u32) = .{},
24compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{},
25/// The topmost block of the current function.
26fn_block: ?*GenZir = null,
27/// String table indexes, keeps track of all `@import` operands.
28imports: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
3729
38/// Call `deinit` on the result.30const InnerError = error{ OutOfMemory, AnalysisFail };
39pub fn init(mod: *Module, decl: *Decl, arena: *Allocator) !AstGen {
40 var astgen: AstGen = .{
41 .mod = mod,
42 .decl = decl,
43 .arena = arena,
44 };
45 // Must be a block instruction at index 0 with the root body.
46 try astgen.instructions.append(mod.gpa, .{
47 .tag = .block,
48 .data = .{ .pl_node = .{
49 .src_node = 0,
50 .payload_index = undefined,
51 } },
52 });
53 return astgen;
54}
5531
56pub fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {32fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {
57 const fields = std.meta.fields(@TypeOf(extra));33 const fields = std.meta.fields(@TypeOf(extra));
58 try astgen.extra.ensureCapacity(astgen.mod.gpa, astgen.extra.items.len + fields.len);34 try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len + fields.len);
59 return addExtraAssumeCapacity(astgen, extra);35 return addExtraAssumeCapacity(astgen, extra);
60}36}
6137
62pub fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {38fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {
63 const fields = std.meta.fields(@TypeOf(extra));39 const fields = std.meta.fields(@TypeOf(extra));
64 const result = @intCast(u32, astgen.extra.items.len);40 const result = @intCast(u32, astgen.extra.items.len);
65 inline for (fields) |field| {41 inline for (fields) |field| {
66 astgen.extra.appendAssumeCapacity(switch (field.field_type) {42 astgen.extra.appendAssumeCapacity(switch (field.field_type) {
67 u32 => @field(extra, field.name),43 u32 => @field(extra, field.name),
68 zir.Inst.Ref => @enumToInt(@field(extra, field.name)),44 Zir.Inst.Ref => @enumToInt(@field(extra, field.name)),
45 i32 => @bitCast(u32, @field(extra, field.name)),
69 else => @compileError("bad field type"),46 else => @compileError("bad field type"),
70 });47 });
71 }48 }
72 return result;49 return result;
73}50}
7451
75pub fn appendRefs(astgen: *AstGen, refs: []const zir.Inst.Ref) !void {52fn appendRefs(astgen: *AstGen, refs: []const Zir.Inst.Ref) !void {
76 const coerced = @bitCast([]const u32, refs);53 const coerced = @bitCast([]const u32, refs);
77 return astgen.extra.appendSlice(astgen.mod.gpa, coerced);54 return astgen.extra.appendSlice(astgen.gpa, coerced);
78}55}
7956
80pub fn appendRefsAssumeCapacity(astgen: *AstGen, refs: []const zir.Inst.Ref) void {57fn appendRefsAssumeCapacity(astgen: *AstGen, refs: []const Zir.Inst.Ref) void {
81 const coerced = @bitCast([]const u32, refs);58 const coerced = @bitCast([]const u32, refs);
82 astgen.extra.appendSliceAssumeCapacity(coerced);59 astgen.extra.appendSliceAssumeCapacity(coerced);
83}60}
8461
85pub fn refIsNoReturn(astgen: AstGen, inst_ref: zir.Inst.Ref) bool {62pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir {
86 if (inst_ref == .unreachable_value) return true;63 var arena = std.heap.ArenaAllocator.init(gpa);
87 if (astgen.refToIndex(inst_ref)) |inst_index| {64 defer arena.deinit();
88 return astgen.instructions.items(.tag)[inst_index].isNoReturn();65
66 var astgen: AstGen = .{
67 .gpa = gpa,
68 .arena = &arena.allocator,
69 .tree = &tree,
70 };
71 defer astgen.deinit(gpa);
72
73 // String table indexes 0 and 1 are reserved for special meaning.
74 try astgen.string_bytes.appendSlice(gpa, &[_]u8{ 0, 0 });
75
76 // We expect at least as many ZIR instructions and extra data items
77 // as AST nodes.
78 try astgen.instructions.ensureTotalCapacity(gpa, tree.nodes.len);
79
80 // First few indexes of extra are reserved and set at the end.
81 const reserved_count = @typeInfo(Zir.ExtraIndex).Enum.fields.len;
82 try astgen.extra.ensureTotalCapacity(gpa, tree.nodes.len + reserved_count);
83 astgen.extra.items.len += reserved_count;
84
85 var top_scope: Scope.Top = .{};
86
87 var gen_scope: GenZir = .{
88 .force_comptime = true,
89 .parent = &top_scope.base,
90 .anon_name_strategy = .parent,
91 .decl_node_index = 0,
92 .decl_line = 0,
93 .astgen = &astgen,
94 };
95 defer gen_scope.instructions.deinit(gpa);
96
97 const container_decl: ast.full.ContainerDecl = .{
98 .layout_token = null,
99 .ast = .{
100 .main_token = undefined,
101 .enum_token = null,
102 .members = tree.rootDecls(),
103 .arg = 0,
104 },
105 };
106 if (AstGen.structDeclInner(
107 &gen_scope,
108 &gen_scope.base,
109 0,
110 container_decl,
111 .Auto,
112 )) |struct_decl_ref| {
113 astgen.extra.items[@enumToInt(Zir.ExtraIndex.main_struct)] = @enumToInt(struct_decl_ref);
114 } else |err| switch (err) {
115 error.OutOfMemory => return error.OutOfMemory,
116 error.AnalysisFail => {}, // Handled via compile_errors below.
89 }117 }
90 return false;
91}
92118
93pub fn indexToRef(astgen: AstGen, inst: zir.Inst.Index) zir.Inst.Ref {119 const err_index = @enumToInt(Zir.ExtraIndex.compile_errors);
94 return @intToEnum(zir.Inst.Ref, astgen.ref_start_index + inst);120 if (astgen.compile_errors.items.len == 0) {
95}121 astgen.extra.items[err_index] = 0;
122 } else {
123 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
124 1 + astgen.compile_errors.items.len *
125 @typeInfo(Zir.Inst.CompileErrors.Item).Struct.fields.len);
126
127 astgen.extra.items[err_index] = astgen.addExtraAssumeCapacity(Zir.Inst.CompileErrors{
128 .items_len = @intCast(u32, astgen.compile_errors.items.len),
129 });
96130
97pub fn refToIndex(astgen: AstGen, inst: zir.Inst.Ref) ?zir.Inst.Index {131 for (astgen.compile_errors.items) |item| {
98 const ref_int = @enumToInt(inst);132 _ = astgen.addExtraAssumeCapacity(item);
99 if (ref_int >= astgen.ref_start_index) {133 }
100 return ref_int - astgen.ref_start_index;134 }
135
136 const imports_index = @enumToInt(Zir.ExtraIndex.imports);
137 if (astgen.imports.count() == 0) {
138 astgen.extra.items[imports_index] = 0;
101 } else {139 } else {
102 return null;140 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
141 @typeInfo(Zir.Inst.Imports).Struct.fields.len + astgen.imports.count());
142
143 astgen.extra.items[imports_index] = astgen.addExtraAssumeCapacity(Zir.Inst.Imports{
144 .imports_len = @intCast(u32, astgen.imports.count()),
145 });
146 for (astgen.imports.items()) |entry| {
147 astgen.extra.appendAssumeCapacity(entry.key);
148 }
103 }149 }
150
151 return Zir{
152 .instructions = astgen.instructions.toOwnedSlice(),
153 .string_bytes = astgen.string_bytes.toOwnedSlice(gpa),
154 .extra = astgen.extra.toOwnedSlice(gpa),
155 };
104}156}
105157
106pub fn deinit(astgen: *AstGen) void {158pub fn deinit(astgen: *AstGen, gpa: *Allocator) void {
107 const gpa = astgen.mod.gpa;
108 astgen.instructions.deinit(gpa);159 astgen.instructions.deinit(gpa);
109 astgen.extra.deinit(gpa);160 astgen.extra.deinit(gpa);
161 astgen.string_table.deinit(gpa);
110 astgen.string_bytes.deinit(gpa);162 astgen.string_bytes.deinit(gpa);
163 astgen.compile_errors.deinit(gpa);
164 astgen.imports.deinit(gpa);
111}165}
112166
113pub const ResultLoc = union(enum) {167pub const ResultLoc = union(enum) {
...@@ -124,16 +178,16 @@ pub const ResultLoc = union(enum) {...@@ -124,16 +178,16 @@ pub const ResultLoc = union(enum) {
124 /// may be treated as `none` instead.178 /// may be treated as `none` instead.
125 none_or_ref,179 none_or_ref,
126 /// The expression will be coerced into this type, but it will be evaluated as an rvalue.180 /// The expression will be coerced into this type, but it will be evaluated as an rvalue.
127 ty: zir.Inst.Ref,181 ty: Zir.Inst.Ref,
128 /// The expression must store its result into this typed pointer. The result instruction182 /// The expression must store its result into this typed pointer. The result instruction
129 /// from the expression must be ignored.183 /// from the expression must be ignored.
130 ptr: zir.Inst.Ref,184 ptr: Zir.Inst.Ref,
131 /// The expression must store its result into this allocation, which has an inferred type.185 /// The expression must store its result into this allocation, which has an inferred type.
132 /// The result instruction from the expression must be ignored.186 /// The result instruction from the expression must be ignored.
133 /// Always an instruction with tag `alloc_inferred`.187 /// Always an instruction with tag `alloc_inferred`.
134 inferred_ptr: zir.Inst.Ref,188 inferred_ptr: Zir.Inst.Ref,
135 /// There is a pointer for the expression to store its result into, however, its type189 /// There is a pointer for the expression to store its result into, however, its type
136 /// is inferred based on peer type resolution for a `zir.Inst.Block`.190 /// is inferred based on peer type resolution for a `Zir.Inst.Block`.
137 /// The result instruction from the expression must be ignored.191 /// The result instruction from the expression must be ignored.
138 block_ptr: *GenZir,192 block_ptr: *GenZir,
139193
...@@ -188,12 +242,20 @@ pub const ResultLoc = union(enum) {...@@ -188,12 +242,20 @@ pub const ResultLoc = union(enum) {
188 }242 }
189};243};
190244
191pub fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerError!zir.Inst.Ref {245pub const align_rl: ResultLoc = .{ .ty = .u16_type };
192 return expr(gz, scope, .{ .ty = .type_type }, type_node);246pub const bool_rl: ResultLoc = .{ .ty = .bool_type };
247
248fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerError!Zir.Inst.Ref {
249 const prev_force_comptime = gz.force_comptime;
250 gz.force_comptime = true;
251 const e = expr(gz, scope, .{ .ty = .type_type }, type_node);
252 gz.force_comptime = prev_force_comptime;
253 return e;
193}254}
194255
195fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {256fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
196 const tree = gz.tree();257 const astgen = gz.astgen;
258 const tree = astgen.tree;
197 const node_tags = tree.nodes.items(.tag);259 const node_tags = tree.nodes.items(.tag);
198 const main_tokens = tree.nodes.items(.main_token);260 const main_tokens = tree.nodes.items(.main_token);
199 switch (node_tags[node]) {261 switch (node_tags[node]) {
...@@ -351,7 +413,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Ins...@@ -351,7 +413,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Ins
351 .@"comptime",413 .@"comptime",
352 .@"nosuspend",414 .@"nosuspend",
353 .error_value,415 .error_value,
354 => return gz.astgen.mod.failNode(scope, node, "invalid left-hand side to assignment", .{}),416 => return astgen.failNode(node, "invalid left-hand side to assignment", .{}),
355417
356 .builtin_call,418 .builtin_call,
357 .builtin_call_comma,419 .builtin_call_comma,
...@@ -364,7 +426,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Ins...@@ -364,7 +426,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Ins
364 // let it pass, and the error will be "invalid builtin function" later.426 // let it pass, and the error will be "invalid builtin function" later.
365 if (BuiltinFn.list.get(builtin_name)) |info| {427 if (BuiltinFn.list.get(builtin_name)) |info| {
366 if (!info.allows_lvalue) {428 if (!info.allows_lvalue) {
367 return gz.astgen.mod.failNode(scope, node, "invalid left-hand side to assignment", .{});429 return astgen.failNode(node, "invalid left-hand side to assignment", .{});
368 }430 }
369 }431 }
370 },432 },
...@@ -386,9 +448,9 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Ins...@@ -386,9 +448,9 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Ins
386/// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the448/// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the
387/// result instruction can be used to inspect whether it is isNoReturn() but that is it,449/// result instruction can be used to inspect whether it is isNoReturn() but that is it,
388/// it must otherwise not be used.450/// it must otherwise not be used.
389pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref {451fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
390 const mod = gz.astgen.mod;452 const astgen = gz.astgen;
391 const tree = gz.tree();453 const tree = astgen.tree;
392 const main_tokens = tree.nodes.items(.main_token);454 const main_tokens = tree.nodes.items(.main_token);
393 const token_tags = tree.tokens.items(.tag);455 const token_tags = tree.tokens.items(.tag);
394 const node_datas = tree.nodes.items(.data);456 const node_datas = tree.nodes.items(.data);
...@@ -407,6 +469,8 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -407,6 +469,8 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
407 .local_var_decl => unreachable, // Handled in `blockExpr`.469 .local_var_decl => unreachable, // Handled in `blockExpr`.
408 .simple_var_decl => unreachable, // Handled in `blockExpr`.470 .simple_var_decl => unreachable, // Handled in `blockExpr`.
409 .aligned_var_decl => unreachable, // Handled in `blockExpr`.471 .aligned_var_decl => unreachable, // Handled in `blockExpr`.
472 .@"defer" => unreachable, // Handled in `blockExpr`.
473 .@"errdefer" => unreachable, // Handled in `blockExpr`.
410474
411 .switch_case => unreachable, // Handled in `switchExpr`.475 .switch_case => unreachable, // Handled in `switchExpr`.
412 .switch_case_one => unreachable, // Handled in `switchExpr`.476 .switch_case_one => unreachable, // Handled in `switchExpr`.
...@@ -415,24 +479,28 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -415,24 +479,28 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
415 .asm_output => unreachable, // Handled in `asmExpr`.479 .asm_output => unreachable, // Handled in `asmExpr`.
416 .asm_input => unreachable, // Handled in `asmExpr`.480 .asm_input => unreachable, // Handled in `asmExpr`.
417481
482 .@"anytype" => unreachable, // Handled in `containerDecl`.
483
418 .assign => {484 .assign => {
419 try assign(gz, scope, node);485 try assign(gz, scope, node);
420 return rvalue(gz, scope, rl, .void_value, node);486 return rvalue(gz, scope, rl, .void_value, node);
421 },487 },
422 .assign_bit_and => {488
423 try assignOp(gz, scope, node, .bit_and);489 .assign_bit_shift_left => {
490 try assignShift(gz, scope, node, .shl);
424 return rvalue(gz, scope, rl, .void_value, node);491 return rvalue(gz, scope, rl, .void_value, node);
425 },492 },
426 .assign_bit_or => {493 .assign_bit_shift_right => {
427 try assignOp(gz, scope, node, .bit_or);494 try assignShift(gz, scope, node, .shr);
428 return rvalue(gz, scope, rl, .void_value, node);495 return rvalue(gz, scope, rl, .void_value, node);
429 },496 },
430 .assign_bit_shift_left => {497
431 try assignOp(gz, scope, node, .shl);498 .assign_bit_and => {
499 try assignOp(gz, scope, node, .bit_and);
432 return rvalue(gz, scope, rl, .void_value, node);500 return rvalue(gz, scope, rl, .void_value, node);
433 },501 },
434 .assign_bit_shift_right => {502 .assign_bit_or => {
435 try assignOp(gz, scope, node, .shr);503 try assignOp(gz, scope, node, .bit_or);
436 return rvalue(gz, scope, rl, .void_value, node);504 return rvalue(gz, scope, rl, .void_value, node);
437 },505 },
438 .assign_bit_xor => {506 .assign_bit_xor => {
...@@ -472,51 +540,54 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -472,51 +540,54 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
472 return rvalue(gz, scope, rl, .void_value, node);540 return rvalue(gz, scope, rl, .void_value, node);
473 },541 },
474542
475 .add => return simpleBinOp(gz, scope, rl, node, .add),543 // zig fmt: off
544 .bit_shift_left => return shiftOp(gz, scope, rl, node, node_datas[node].lhs, node_datas[node].rhs, .shl),
545 .bit_shift_right => return shiftOp(gz, scope, rl, node, node_datas[node].lhs, node_datas[node].rhs, .shr),
546
547 .add => return simpleBinOp(gz, scope, rl, node, .add),
476 .add_wrap => return simpleBinOp(gz, scope, rl, node, .addwrap),548 .add_wrap => return simpleBinOp(gz, scope, rl, node, .addwrap),
477 .sub => return simpleBinOp(gz, scope, rl, node, .sub),549 .sub => return simpleBinOp(gz, scope, rl, node, .sub),
478 .sub_wrap => return simpleBinOp(gz, scope, rl, node, .subwrap),550 .sub_wrap => return simpleBinOp(gz, scope, rl, node, .subwrap),
479 .mul => return simpleBinOp(gz, scope, rl, node, .mul),551 .mul => return simpleBinOp(gz, scope, rl, node, .mul),
480 .mul_wrap => return simpleBinOp(gz, scope, rl, node, .mulwrap),552 .mul_wrap => return simpleBinOp(gz, scope, rl, node, .mulwrap),
481 .div => return simpleBinOp(gz, scope, rl, node, .div),553 .div => return simpleBinOp(gz, scope, rl, node, .div),
482 .mod => return simpleBinOp(gz, scope, rl, node, .mod_rem),554 .mod => return simpleBinOp(gz, scope, rl, node, .mod_rem),
483 .bit_and => return simpleBinOp(gz, scope, rl, node, .bit_and),555 .bit_and => return simpleBinOp(gz, scope, rl, node, .bit_and),
484 .bit_or => return simpleBinOp(gz, scope, rl, node, .bit_or),556 .bit_or => return simpleBinOp(gz, scope, rl, node, .bit_or),
485 .bit_shift_left => return simpleBinOp(gz, scope, rl, node, .shl),557 .bit_xor => return simpleBinOp(gz, scope, rl, node, .xor),
486 .bit_shift_right => return simpleBinOp(gz, scope, rl, node, .shr),558
487 .bit_xor => return simpleBinOp(gz, scope, rl, node, .xor),559 .bang_equal => return simpleBinOp(gz, scope, rl, node, .cmp_neq),
488560 .equal_equal => return simpleBinOp(gz, scope, rl, node, .cmp_eq),
489 .bang_equal => return simpleBinOp(gz, scope, rl, node, .cmp_neq),561 .greater_than => return simpleBinOp(gz, scope, rl, node, .cmp_gt),
490 .equal_equal => return simpleBinOp(gz, scope, rl, node, .cmp_eq),
491 .greater_than => return simpleBinOp(gz, scope, rl, node, .cmp_gt),
492 .greater_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_gte),562 .greater_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_gte),
493 .less_than => return simpleBinOp(gz, scope, rl, node, .cmp_lt),563 .less_than => return simpleBinOp(gz, scope, rl, node, .cmp_lt),
494 .less_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_lte),564 .less_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_lte),
495565
496 .array_cat => return simpleBinOp(gz, scope, rl, node, .array_cat),566 .array_cat => return simpleBinOp(gz, scope, rl, node, .array_cat),
497 .array_mult => return simpleBinOp(gz, scope, rl, node, .array_mul),567 .array_mult => return simpleBinOp(gz, scope, rl, node, .array_mul),
498568
499 .error_union => return simpleBinOp(gz, scope, rl, node, .error_union_type),569 .error_union => return simpleBinOp(gz, scope, rl, node, .error_union_type),
500 .merge_error_sets => return simpleBinOp(gz, scope, rl, node, .merge_error_sets),570 .merge_error_sets => return simpleBinOp(gz, scope, rl, node, .merge_error_sets),
501571
502 .bool_and => return boolBinOp(gz, scope, rl, node, .bool_br_and),572 .bool_and => return boolBinOp(gz, scope, rl, node, .bool_br_and),
503 .bool_or => return boolBinOp(gz, scope, rl, node, .bool_br_or),573 .bool_or => return boolBinOp(gz, scope, rl, node, .bool_br_or),
504574
505 .bool_not => return boolNot(gz, scope, rl, node),575 .bool_not => return boolNot(gz, scope, rl, node),
506 .bit_not => return bitNot(gz, scope, rl, node),576 .bit_not => return bitNot(gz, scope, rl, node),
507577
508 .negation => return negation(gz, scope, rl, node, .negate),578 .negation => return negation(gz, scope, rl, node, .negate),
509 .negation_wrap => return negation(gz, scope, rl, node, .negate_wrap),579 .negation_wrap => return negation(gz, scope, rl, node, .negate_wrap),
510580
511 .identifier => return identifier(gz, scope, rl, node),581 .identifier => return identifier(gz, scope, rl, node),
512582
513 .asm_simple => return asmExpr(gz, scope, rl, node, tree.asmSimple(node)),583 .asm_simple => return asmExpr(gz, scope, rl, node, tree.asmSimple(node)),
514 .@"asm" => return asmExpr(gz, scope, rl, node, tree.asmFull(node)),584 .@"asm" => return asmExpr(gz, scope, rl, node, tree.asmFull(node)),
515585
516 .string_literal => return stringLiteral(gz, scope, rl, node),586 .string_literal => return stringLiteral(gz, scope, rl, node),
517 .multiline_string_literal => return multilineStringLiteral(gz, scope, rl, node),587 .multiline_string_literal => return multilineStringLiteral(gz, scope, rl, node),
518588
519 .integer_literal => return integerLiteral(gz, scope, rl, node),589 .integer_literal => return integerLiteral(gz, scope, rl, node),
590 // zig fmt: on
520591
521 .builtin_call_two, .builtin_call_two_comma => {592 .builtin_call_two, .builtin_call_two_comma => {
522 if (node_datas[node].lhs == 0) {593 if (node_datas[node].lhs == 0) {
...@@ -548,10 +619,10 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -548,10 +619,10 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
548 .tag = .@"unreachable",619 .tag = .@"unreachable",
549 .data = .{ .@"unreachable" = .{620 .data = .{ .@"unreachable" = .{
550 .safety = true,621 .safety = true,
551 .src_node = gz.astgen.decl.nodeIndexToRelative(node),622 .src_node = gz.nodeIndexToRelative(node),
552 } },623 } },
553 });624 });
554 return zir.Inst.Ref.unreachable_value;625 return Zir.Inst.Ref.unreachable_value;
555 },626 },
556 .@"return" => return ret(gz, scope, node),627 .@"return" => return ret(gz, scope, node),
557 .field_access => return fieldAccess(gz, scope, rl, node),628 .field_access => return fieldAccess(gz, scope, rl, node),
...@@ -570,7 +641,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -570,7 +641,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
570 .slice_open => {641 .slice_open => {
571 const lhs = try expr(gz, scope, .ref, node_datas[node].lhs);642 const lhs = try expr(gz, scope, .ref, node_datas[node].lhs);
572 const start = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs);643 const start = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs);
573 const result = try gz.addPlNode(.slice_start, node, zir.Inst.SliceStart{644 const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{
574 .lhs = lhs,645 .lhs = lhs,
575 .start = start,646 .start = start,
576 });647 });
...@@ -581,7 +652,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -581,7 +652,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
581 const extra = tree.extraData(node_datas[node].rhs, ast.Node.Slice);652 const extra = tree.extraData(node_datas[node].rhs, ast.Node.Slice);
582 const start = try expr(gz, scope, .{ .ty = .usize_type }, extra.start);653 const start = try expr(gz, scope, .{ .ty = .usize_type }, extra.start);
583 const end = try expr(gz, scope, .{ .ty = .usize_type }, extra.end);654 const end = try expr(gz, scope, .{ .ty = .usize_type }, extra.end);
584 const result = try gz.addPlNode(.slice_end, node, zir.Inst.SliceEnd{655 const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{
585 .lhs = lhs,656 .lhs = lhs,
586 .start = start,657 .start = start,
587 .end = end,658 .end = end,
...@@ -594,7 +665,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -594,7 +665,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
594 const start = try expr(gz, scope, .{ .ty = .usize_type }, extra.start);665 const start = try expr(gz, scope, .{ .ty = .usize_type }, extra.start);
595 const end = try expr(gz, scope, .{ .ty = .usize_type }, extra.end);666 const end = try expr(gz, scope, .{ .ty = .usize_type }, extra.end);
596 const sentinel = try expr(gz, scope, .{ .ty = .usize_type }, extra.sentinel);667 const sentinel = try expr(gz, scope, .{ .ty = .usize_type }, extra.sentinel);
597 const result = try gz.addPlNode(.slice_sentinel, node, zir.Inst.SliceSentinel{668 const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{
598 .lhs = lhs,669 .lhs = lhs,
599 .start = start,670 .start = start,
600 .end = end,671 .end = end,
...@@ -654,8 +725,12 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -654,8 +725,12 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
654 },725 },
655 .enum_literal => return simpleStrTok(gz, scope, rl, main_tokens[node], node, .enum_literal),726 .enum_literal => return simpleStrTok(gz, scope, rl, main_tokens[node], node, .enum_literal),
656 .error_value => return simpleStrTok(gz, scope, rl, node_datas[node].rhs, node, .error_value),727 .error_value => return simpleStrTok(gz, scope, rl, node_datas[node].rhs, node, .error_value),
657 .anyframe_literal => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),728 .anyframe_literal => return rvalue(gz, scope, rl, .anyframe_type, node),
658 .anyframe_type => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),729 .anyframe_type => {
730 const return_type = try typeExpr(gz, scope, node_datas[node].rhs);
731 const result = try gz.addUnNode(.anyframe_type, return_type, node);
732 return rvalue(gz, scope, rl, result, node);
733 },
659 .@"catch" => {734 .@"catch" => {
660 const catch_token = main_tokens[node];735 const catch_token = main_tokens[node];
661 const payload_token: ?ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe)736 const payload_token: ?ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe)
...@@ -751,27 +826,30 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -751,27 +826,30 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
751 .char_literal => return charLiteral(gz, scope, rl, node),826 .char_literal => return charLiteral(gz, scope, rl, node),
752 .error_set_decl => return errorSetDecl(gz, scope, rl, node),827 .error_set_decl => return errorSetDecl(gz, scope, rl, node),
753 .array_access => return arrayAccess(gz, scope, rl, node),828 .array_access => return arrayAccess(gz, scope, rl, node),
754 .@"comptime" => return comptimeExpr(gz, scope, rl, node_datas[node].lhs),829 .@"comptime" => return comptimeExprAst(gz, scope, rl, node),
755 .@"switch", .switch_comma => return switchExpr(gz, scope, rl, node),830 .@"switch", .switch_comma => return switchExpr(gz, scope, rl, node),
756831
757 .@"nosuspend" => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),832 .@"nosuspend" => return nosuspendExpr(gz, scope, rl, node),
758 .@"suspend" => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),833 .@"suspend" => return suspendExpr(gz, scope, rl, node),
759 .@"await" => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),834 .@"await" => return awaitExpr(gz, scope, rl, node),
760 .@"resume" => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),835 .@"resume" => return resumeExpr(gz, scope, rl, node),
761836
762 .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}),837 .@"try" => return tryExpr(gz, scope, rl, node, node_datas[node].lhs),
763 .@"errdefer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .errdefer", .{}),
764 .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
765838
766 .array_init_one,839 .array_init_one, .array_init_one_comma => {
767 .array_init_one_comma,840 var elements: [1]ast.Node.Index = undefined;
768 .array_init_dot_two,841 return arrayInitExpr(gz, scope, rl, node, tree.arrayInitOne(&elements, node));
769 .array_init_dot_two_comma,842 },
843 .array_init_dot_two, .array_init_dot_two_comma => {
844 var elements: [2]ast.Node.Index = undefined;
845 return arrayInitExpr(gz, scope, rl, node, tree.arrayInitDotTwo(&elements, node));
846 },
770 .array_init_dot,847 .array_init_dot,
771 .array_init_dot_comma,848 .array_init_dot_comma,
849 => return arrayInitExpr(gz, scope, rl, node, tree.arrayInitDot(node)),
772 .array_init,850 .array_init,
773 .array_init_comma,851 .array_init_comma,
774 => return mod.failNode(scope, node, "TODO implement astgen.expr for array literals", .{}),852 => return arrayInitExpr(gz, scope, rl, node, tree.arrayInit(node)),
775853
776 .struct_init_one, .struct_init_one_comma => {854 .struct_init_one, .struct_init_one_comma => {
777 var fields: [1]ast.Node.Index = undefined;855 var fields: [1]ast.Node.Index = undefined;
...@@ -788,3655 +866,6498 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -788,3655 +866,6498 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
788 .struct_init_comma,866 .struct_init_comma,
789 => return structInitExpr(gz, scope, rl, node, tree.structInit(node)),867 => return structInitExpr(gz, scope, rl, node, tree.structInit(node)),
790868
791 .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}),869 .fn_proto_simple => {
792 .fn_proto_simple,870 var params: [1]ast.Node.Index = undefined;
793 .fn_proto_multi,871 return fnProtoExpr(gz, scope, rl, tree.fnProtoSimple(&params, node));
794 .fn_proto_one,872 },
795 .fn_proto,873 .fn_proto_multi => {
796 => return mod.failNode(scope, node, "TODO implement astgen.expr for function prototypes", .{}),874 return fnProtoExpr(gz, scope, rl, tree.fnProtoMulti(node));
875 },
876 .fn_proto_one => {
877 var params: [1]ast.Node.Index = undefined;
878 return fnProtoExpr(gz, scope, rl, tree.fnProtoOne(&params, node));
879 },
880 .fn_proto => {
881 return fnProtoExpr(gz, scope, rl, tree.fnProto(node));
882 },
797 }883 }
798}884}
799885
800pub fn structInitExpr(886fn nosuspendExpr(
801 gz: *GenZir,887 gz: *GenZir,
802 scope: *Scope,888 scope: *Scope,
803 rl: ResultLoc,889 rl: ResultLoc,
804 node: ast.Node.Index,890 node: ast.Node.Index,
805 struct_init: ast.full.StructInit,891) InnerError!Zir.Inst.Ref {
806) InnerError!zir.Inst.Ref {
807 const tree = gz.tree();
808 const astgen = gz.astgen;892 const astgen = gz.astgen;
809 const mod = astgen.mod;893 const gpa = astgen.gpa;
810 const gpa = mod.gpa;894 const tree = astgen.tree;
895 const node_datas = tree.nodes.items(.data);
896 const body_node = node_datas[node].lhs;
897 assert(body_node != 0);
898 if (gz.nosuspend_node != 0) {
899 return astgen.failNodeNotes(node, "redundant nosuspend block", .{}, &[_]u32{
900 try astgen.errNoteNode(gz.nosuspend_node, "other nosuspend block here", .{}),
901 });
902 }
903 gz.nosuspend_node = node;
904 const result = try expr(gz, scope, rl, body_node);
905 gz.nosuspend_node = 0;
906 return rvalue(gz, scope, rl, result, node);
907}
811908
812 if (struct_init.ast.fields.len == 0) {909fn suspendExpr(
813 if (struct_init.ast.type_expr == 0) {910 gz: *GenZir,
814 return rvalue(gz, scope, rl, .empty_struct, node);911 scope: *Scope,
815 } else {912 rl: ResultLoc,
816 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);913 node: ast.Node.Index,
817 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);914) InnerError!Zir.Inst.Ref {
818 return rvalue(gz, scope, rl, result, node);915 const astgen = gz.astgen;
819 }916 const gpa = astgen.gpa;
917 const tree = astgen.tree;
918 const node_datas = tree.nodes.items(.data);
919 const body_node = node_datas[node].lhs;
920
921 if (gz.nosuspend_node != 0) {
922 return astgen.failNodeNotes(node, "suspend inside nosuspend block", .{}, &[_]u32{
923 try astgen.errNoteNode(gz.nosuspend_node, "nosuspend block here", .{}),
924 });
820 }925 }
821 switch (rl) {926 if (gz.suspend_node != 0) {
822 .discard => return mod.failNode(scope, node, "TODO implement structInitExpr discard", .{}),927 return astgen.failNodeNotes(node, "cannot suspend inside suspend block", .{}, &[_]u32{
823 .none, .none_or_ref => return mod.failNode(scope, node, "TODO implement structInitExpr none", .{}),928 try astgen.errNoteNode(gz.suspend_node, "other suspend block here", .{}),
824 .ref => unreachable, // struct literal not valid as l-value929 });
825 .ty => |ty_inst| {930 }
826 const fields_list = try gpa.alloc(zir.Inst.StructInit.Item, struct_init.ast.fields.len);931 assert(body_node != 0);
827 defer gpa.free(fields_list);
828932
829 for (struct_init.ast.fields) |field_init, i| {933 const suspend_inst = try gz.addBlock(.suspend_block, node);
830 const name_token = tree.firstToken(field_init) - 2;934 try gz.instructions.append(gpa, suspend_inst);
831 const str_index = try gz.identAsString(name_token);
832935
833 const field_ty_inst = try gz.addPlNode(.field_type, field_init, zir.Inst.FieldType{936 var suspend_scope = gz.makeSubBlock(scope);
834 .container_type = ty_inst,937 suspend_scope.suspend_node = node;
835 .name_start = str_index,938 defer suspend_scope.instructions.deinit(gpa);
836 });939
837 fields_list[i] = .{940 const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node);
838 .field_type = astgen.refToIndex(field_ty_inst).?,941 if (!gz.refIsNoReturn(body_result)) {
839 .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init),942 _ = try suspend_scope.addBreak(.break_inline, suspend_inst, .void_value);
840 };
841 }
842 const init_inst = try gz.addPlNode(.struct_init, node, zir.Inst.StructInit{
843 .fields_len = @intCast(u32, fields_list.len),
844 });
845 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
846 fields_list.len * @typeInfo(zir.Inst.StructInit.Item).Struct.fields.len);
847 for (fields_list) |field| {
848 _ = gz.astgen.addExtraAssumeCapacity(field);
849 }
850 return rvalue(gz, scope, rl, init_inst, node);
851 },
852 .ptr => |ptr_inst| {
853 const field_ptr_list = try gpa.alloc(zir.Inst.Index, struct_init.ast.fields.len);
854 defer gpa.free(field_ptr_list);
855
856 for (struct_init.ast.fields) |field_init, i| {
857 const name_token = tree.firstToken(field_init) - 2;
858 const str_index = try gz.identAsString(name_token);
859 const field_ptr = try gz.addPlNode(.field_ptr, field_init, zir.Inst.Field{
860 .lhs = ptr_inst,
861 .field_name_start = str_index,
862 });
863 field_ptr_list[i] = astgen.refToIndex(field_ptr).?;
864 _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init);
865 }
866 const validate_inst = try gz.addPlNode(.validate_struct_init_ptr, node, zir.Inst.Block{
867 .body_len = @intCast(u32, field_ptr_list.len),
868 });
869 try astgen.extra.appendSlice(gpa, field_ptr_list);
870 return validate_inst;
871 },
872 .inferred_ptr => |ptr_inst| {
873 return mod.failNode(scope, node, "TODO implement structInitExpr inferred_ptr", .{});
874 },
875 .block_ptr => |block_gz| {
876 return mod.failNode(scope, node, "TODO implement structInitExpr block", .{});
877 },
878 }943 }
944 try suspend_scope.setBlockBody(suspend_inst);
945
946 return gz.indexToRef(suspend_inst);
879}947}
880948
881pub fn comptimeExpr(949fn awaitExpr(
882 gz: *GenZir,950 gz: *GenZir,
883 scope: *Scope,951 scope: *Scope,
884 rl: ResultLoc,952 rl: ResultLoc,
885 node: ast.Node.Index,953 node: ast.Node.Index,
886) InnerError!zir.Inst.Ref {954) InnerError!Zir.Inst.Ref {
887 const prev_force_comptime = gz.force_comptime;955 const astgen = gz.astgen;
888 gz.force_comptime = true;956 const tree = astgen.tree;
889 const result = try expr(gz, scope, rl, node);
890 gz.force_comptime = prev_force_comptime;
891 return result;
892}
893
894fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {
895 const mod = parent_gz.astgen.mod;
896 const tree = parent_gz.tree();
897 const node_datas = tree.nodes.items(.data);957 const node_datas = tree.nodes.items(.data);
898 const break_label = node_datas[node].lhs;958 const rhs_node = node_datas[node].lhs;
899 const rhs = node_datas[node].rhs;
900959
901 // Look for the label in the scope.960 if (gz.suspend_node != 0) {
902 var scope = parent_scope;961 return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{
903 while (true) {962 try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}),
904 switch (scope.tag) {963 });
905 .gen_zir => {964 }
906 const block_gz = scope.cast(GenZir).?;965 const operand = try expr(gz, scope, .none, rhs_node);
966 const tag: Zir.Inst.Tag = if (gz.nosuspend_node != 0) .await_nosuspend else .@"await";
967 const result = try gz.addUnNode(tag, operand, node);
968 return rvalue(gz, scope, rl, result, node);
969}
907970
908 const block_inst = blk: {971fn resumeExpr(
909 if (break_label != 0) {972 gz: *GenZir,
910 if (block_gz.label) |*label| {973 scope: *Scope,
911 if (try tokenIdentEql(mod, parent_scope, label.token, break_label)) {974 rl: ResultLoc,
912 label.used = true;975 node: ast.Node.Index,
913 break :blk label.block_inst;976) InnerError!Zir.Inst.Ref {
914 }977 const astgen = gz.astgen;
915 }978 const tree = astgen.tree;
916 } else if (block_gz.break_block != 0) {979 const node_datas = tree.nodes.items(.data);
917 break :blk block_gz.break_block;980 const rhs_node = node_datas[node].lhs;
918 }981 const operand = try expr(gz, scope, .none, rhs_node);
919 scope = block_gz.parent;982 const result = try gz.addUnNode(.@"resume", operand, node);
920 continue;983 return rvalue(gz, scope, rl, result, node);
921 };984}
922985
923 if (rhs == 0) {986fn fnProtoExpr(
924 _ = try parent_gz.addBreak(.@"break", block_inst, .void_value);987 gz: *GenZir,
925 return zir.Inst.Ref.unreachable_value;988 scope: *Scope,
926 }989 rl: ResultLoc,
927 block_gz.break_count += 1;990 fn_proto: ast.full.FnProto,
928 const prev_rvalue_rl_count = block_gz.rvalue_rl_count;991) InnerError!Zir.Inst.Ref {
929 const operand = try expr(parent_gz, parent_scope, block_gz.break_result_loc, rhs);992 const astgen = gz.astgen;
930 const have_store_to_block = block_gz.rvalue_rl_count != prev_rvalue_rl_count;993 const gpa = astgen.gpa;
994 const tree = astgen.tree;
995 const token_tags = tree.tokens.items(.tag);
931996
932 const br = try parent_gz.addBreak(.@"break", block_inst, operand);997 const is_extern = blk: {
998 const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false;
999 break :blk token_tags[maybe_extern_token] == .keyword_extern;
1000 };
1001 assert(!is_extern);
9331002
934 if (block_gz.break_result_loc == .block_ptr) {1003 // The AST params array does not contain anytype and ... parameters.
935 try block_gz.labeled_breaks.append(mod.gpa, br);1004 // We must iterate to count how many param types to allocate.
1005 const param_count = blk: {
1006 var count: usize = 0;
1007 var it = fn_proto.iterate(tree.*);
1008 while (it.next()) |param| {
1009 if (param.anytype_ellipsis3) |token| switch (token_tags[token]) {
1010 .ellipsis3 => break,
1011 .keyword_anytype => {},
1012 else => unreachable,
1013 };
1014 count += 1;
1015 }
1016 break :blk count;
1017 };
1018 const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);
1019 defer gpa.free(param_types);
9361020
937 if (have_store_to_block) {1021 var is_var_args = false;
938 const zir_tags = parent_gz.astgen.instructions.items(.tag);1022 {
939 const zir_datas = parent_gz.astgen.instructions.items(.data);1023 var param_type_i: usize = 0;
940 const store_inst = @intCast(u32, zir_tags.len - 2);1024 var it = fn_proto.iterate(tree.*);
941 assert(zir_tags[store_inst] == .store_to_block_ptr);1025 while (it.next()) |param| : (param_type_i += 1) {
942 assert(zir_datas[store_inst].bin.lhs == block_gz.rl_ptr);1026 if (param.anytype_ellipsis3) |token| {
943 try block_gz.labeled_store_to_block_ptr_list.append(mod.gpa, store_inst);1027 switch (token_tags[token]) {
944 }1028 .keyword_anytype => {
1029 param_types[param_type_i] = .none;
1030 continue;
1031 },
1032 .ellipsis3 => {
1033 is_var_args = true;
1034 break;
1035 },
1036 else => unreachable,
945 }1037 }
946 return zir.Inst.Ref.unreachable_value;1038 }
947 },1039 const param_type_node = param.type_expr;
948 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,1040 assert(param_type_node != 0);
949 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,1041 param_types[param_type_i] =
950 else => if (break_label != 0) {1042 try expr(gz, scope, .{ .ty = .type_type }, param_type_node);
951 const label_name = try mod.identifierTokenString(parent_scope, break_label);
952 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});
953 } else {
954 return mod.failNode(parent_scope, node, "break expression outside loop", .{});
955 },
956 }1043 }
1044 assert(param_type_i == param_count);
957 }1045 }
958}
959
960fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {
961 const mod = parent_gz.astgen.mod;
962 const tree = parent_gz.tree();
963 const node_datas = tree.nodes.items(.data);
964 const break_label = node_datas[node].lhs;
9651046
966 // Look for the label in the scope.1047 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
967 var scope = parent_scope;1048 break :inst try expr(gz, scope, align_rl, fn_proto.ast.align_expr);
968 while (true) {1049 };
969 switch (scope.tag) {1050 if (fn_proto.ast.section_expr != 0) {
970 .gen_zir => {1051 return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{});
971 const gen_zir = scope.cast(GenZir).?;1052 }
972 const continue_block = gen_zir.continue_block;
973 if (continue_block == 0) {
974 scope = gen_zir.parent;
975 continue;
976 }
977 if (break_label != 0) blk: {
978 if (gen_zir.label) |*label| {
979 if (try tokenIdentEql(mod, parent_scope, label.token, break_label)) {
980 label.used = true;
981 break :blk;
982 }
983 }
984 // found continue but either it has a different label, or no label
985 scope = gen_zir.parent;
986 continue;
987 }
9881053
989 // TODO emit a break_inline if the loop being continued is inline1054 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
990 _ = try parent_gz.addBreak(.@"break", continue_block, .void_value);1055 const is_inferred_error = token_tags[maybe_bang] == .bang;
991 return zir.Inst.Ref.unreachable_value;1056 if (is_inferred_error) {
992 },1057 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
993 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
994 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
995 else => if (break_label != 0) {
996 const label_name = try mod.identifierTokenString(parent_scope, break_label);
997 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});
998 } else {
999 return mod.failNode(parent_scope, node, "continue expression outside loop", .{});
1000 },
1001 }
1002 }1058 }
1059 const return_type_inst = try AstGen.expr(
1060 gz,
1061 scope,
1062 .{ .ty = .type_type },
1063 fn_proto.ast.return_type,
1064 );
1065
1066 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
1067 try AstGen.expr(
1068 gz,
1069 scope,
1070 .{ .ty = .calling_convention_type },
1071 fn_proto.ast.callconv_expr,
1072 )
1073 else
1074 Zir.Inst.Ref.none;
1075
1076 const result = try gz.addFunc(.{
1077 .src_node = fn_proto.ast.proto_node,
1078 .ret_ty = return_type_inst,
1079 .param_types = param_types,
1080 .body = &[0]Zir.Inst.Index{},
1081 .cc = cc,
1082 .align_inst = align_inst,
1083 .lib_name = 0,
1084 .is_var_args = is_var_args,
1085 .is_inferred_error = false,
1086 .is_test = false,
1087 .is_extern = false,
1088 });
1089 return rvalue(gz, scope, rl, result, fn_proto.ast.proto_node);
1003}1090}
10041091
1005pub fn blockExpr(1092fn arrayInitExpr(
1006 gz: *GenZir,1093 gz: *GenZir,
1007 scope: *Scope,1094 scope: *Scope,
1008 rl: ResultLoc,1095 rl: ResultLoc,
1009 block_node: ast.Node.Index,1096 node: ast.Node.Index,
1010 statements: []const ast.Node.Index,1097 array_init: ast.full.ArrayInit,
1011) InnerError!zir.Inst.Ref {1098) InnerError!Zir.Inst.Ref {
1012 const tracy = trace(@src());1099 const astgen = gz.astgen;
1013 defer tracy.end();1100 const tree = astgen.tree;
10141101 const gpa = astgen.gpa;
1015 const tree = gz.tree();1102 const node_tags = tree.nodes.items(.tag);
1016 const main_tokens = tree.nodes.items(.main_token);1103 const main_tokens = tree.nodes.items(.main_token);
1017 const token_tags = tree.tokens.items(.tag);
10181104
1019 const lbrace = main_tokens[block_node];1105 assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.
1020 if (token_tags[lbrace - 1] == .colon and
1021 token_tags[lbrace - 2] == .identifier)
1022 {
1023 return labeledBlockExpr(gz, scope, rl, block_node, statements, .block);
1024 }
10251106
1026 try blockExprStmts(gz, scope, block_node, statements);1107 const types: struct {
1027 return rvalue(gz, scope, rl, .void_value, block_node);1108 array: Zir.Inst.Ref,
1028}1109 elem: Zir.Inst.Ref,
1110 } = inst: {
1111 if (array_init.ast.type_expr == 0) break :inst .{
1112 .array = .none,
1113 .elem = .none,
1114 };
10291115
1030fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIndex) !void {1116 infer: {
1031 // Look for the label in the scope.1117 const array_type: ast.full.ArrayType = switch (node_tags[array_init.ast.type_expr]) {
1032 var scope = parent_scope;1118 .array_type => tree.arrayType(array_init.ast.type_expr),
1033 while (true) {1119 .array_type_sentinel => tree.arrayTypeSentinel(array_init.ast.type_expr),
1034 switch (scope.tag) {1120 else => break :infer,
1035 .gen_zir => {1121 };
1036 const gen_zir = scope.cast(GenZir).?;1122 // This intentionally does not support `@"_"` syntax.
1037 if (gen_zir.label) |prev_label| {1123 if (node_tags[array_type.ast.elem_count] == .identifier and
1038 if (try tokenIdentEql(mod, parent_scope, label, prev_label.token)) {1124 mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_"))
1039 const tree = parent_scope.tree();1125 {
1040 const main_tokens = tree.nodes.items(.main_token);1126 const len_inst = try gz.addInt(array_init.ast.elements.len);
10411127 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
1042 const label_name = try mod.identifierTokenString(parent_scope, label);1128 if (array_type.ast.sentinel == 0) {
1043 const msg = msg: {1129 const array_type_inst = try gz.addBin(.array_type, len_inst, elem_type);
1044 const msg = try mod.errMsg(1130 break :inst .{
1045 parent_scope,1131 .array = array_type_inst,
1046 gen_zir.tokSrcLoc(label),1132 .elem = elem_type,
1047 "redefinition of label '{s}'",1133 };
1048 .{label_name},1134 } else {
1049 );1135 const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel);
1050 errdefer msg.destroy(mod.gpa);1136 const array_type_inst = try gz.addArrayTypeSentinel(len_inst, elem_type, sentinel);
1051 try mod.errNote(1137 break :inst .{
1052 parent_scope,1138 .array = array_type_inst,
1053 gen_zir.tokSrcLoc(prev_label.token),1139 .elem = elem_type,
1054 msg,1140 };
1055 "previous definition is here",
1056 .{},
1057 );
1058 break :msg msg;
1059 };
1060 return mod.failWithOwnedErrorMsg(parent_scope, msg);
1061 }
1062 }1141 }
1063 scope = gen_zir.parent;1142 }
1064 },
1065 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
1066 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1067 else => return,
1068 }1143 }
1144 const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
1145 const elem_type = try gz.addUnNode(.elem_type, array_type_inst, array_init.ast.type_expr);
1146 break :inst .{
1147 .array = array_type_inst,
1148 .elem = elem_type,
1149 };
1150 };
1151
1152 switch (rl) {
1153 .discard => {
1154 for (array_init.ast.elements) |elem_init| {
1155 _ = try expr(gz, scope, .discard, elem_init);
1156 }
1157 return Zir.Inst.Ref.void_value;
1158 },
1159 .ref => {
1160 if (types.array != .none) {
1161 return arrayInitExprRlTy(gz, scope, rl, node, array_init.ast.elements, types.array, types.elem, .array_init_ref);
1162 } else {
1163 return arrayInitExprRlNone(gz, scope, rl, node, array_init.ast.elements, .array_init_anon_ref);
1164 }
1165 },
1166 .none, .none_or_ref => {
1167 if (types.array != .none) {
1168 return arrayInitExprRlTy(gz, scope, rl, node, array_init.ast.elements, types.array, types.elem, .array_init);
1169 } else {
1170 return arrayInitExprRlNone(gz, scope, rl, node, array_init.ast.elements, .array_init_anon);
1171 }
1172 },
1173 .ty => |ty_inst| {
1174 if (types.array != .none) {
1175 const result = try arrayInitExprRlTy(gz, scope, rl, node, array_init.ast.elements, types.array, types.elem, .array_init);
1176 return rvalue(gz, scope, rl, result, node);
1177 } else {
1178 const elem_type = try gz.addUnNode(.elem_type, ty_inst, node);
1179 return arrayInitExprRlTy(gz, scope, rl, node, array_init.ast.elements, ty_inst, elem_type, .array_init);
1180 }
1181 },
1182 .ptr, .inferred_ptr => |ptr_inst| {
1183 return arrayInitExprRlPtr(gz, scope, rl, node, array_init.ast.elements, ptr_inst);
1184 },
1185 .block_ptr => |block_gz| {
1186 return arrayInitExprRlPtr(gz, scope, rl, node, array_init.ast.elements, block_gz.rl_ptr);
1187 },
1069 }1188 }
1070}1189}
10711190
1072fn labeledBlockExpr(1191fn arrayInitExprRlNone(
1073 gz: *GenZir,1192 gz: *GenZir,
1074 parent_scope: *Scope,1193 scope: *Scope,
1075 rl: ResultLoc,1194 rl: ResultLoc,
1076 block_node: ast.Node.Index,1195 node: ast.Node.Index,
1077 statements: []const ast.Node.Index,1196 elements: []const ast.Node.Index,
1078 zir_tag: zir.Inst.Tag,1197 tag: Zir.Inst.Tag,
1079) InnerError!zir.Inst.Ref {1198) InnerError!Zir.Inst.Ref {
1080 const tracy = trace(@src());1199 const astgen = gz.astgen;
1081 defer tracy.end();1200 const gpa = astgen.gpa;
1201 const elem_list = try gpa.alloc(Zir.Inst.Ref, elements.len);
1202 defer gpa.free(elem_list);
10821203
1083 assert(zir_tag == .block);1204 for (elements) |elem_init, i| {
1205 elem_list[i] = try expr(gz, scope, .none, elem_init);
1206 }
1207 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{
1208 .operands_len = @intCast(u32, elem_list.len),
1209 });
1210 try astgen.appendRefs(elem_list);
1211 return init_inst;
1212}
10841213
1085 const mod = gz.astgen.mod;1214fn arrayInitExprRlTy(
1086 const tree = gz.tree();1215 gz: *GenZir,
1087 const main_tokens = tree.nodes.items(.main_token);1216 scope: *Scope,
1088 const token_tags = tree.tokens.items(.tag);1217 rl: ResultLoc,
1218 node: ast.Node.Index,
1219 elements: []const ast.Node.Index,
1220 array_ty_inst: Zir.Inst.Ref,
1221 elem_ty_inst: Zir.Inst.Ref,
1222 tag: Zir.Inst.Tag,
1223) InnerError!Zir.Inst.Ref {
1224 const astgen = gz.astgen;
1225 const gpa = astgen.gpa;
10891226
1090 const lbrace = main_tokens[block_node];1227 const elem_list = try gpa.alloc(Zir.Inst.Ref, elements.len);
1091 const label_token = lbrace - 2;1228 defer gpa.free(elem_list);
1092 assert(token_tags[label_token] == .identifier);
10931229
1094 try checkLabelRedefinition(mod, parent_scope, label_token);1230 const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };
10951231
1096 // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct1232 for (elements) |elem_init, i| {
1097 // so that break statements can reference it.1233 elem_list[i] = try expr(gz, scope, elem_rl, elem_init);
1098 const block_inst = try gz.addBlock(zir_tag, block_node);1234 }
1099 try gz.instructions.append(mod.gpa, block_inst);1235 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{
1236 .operands_len = @intCast(u32, elem_list.len),
1237 });
1238 try astgen.appendRefs(elem_list);
1239 return init_inst;
1240}
11001241
1101 var block_scope: GenZir = .{1242fn arrayInitExprRlPtr(
1102 .parent = parent_scope,1243 gz: *GenZir,
1103 .astgen = gz.astgen,1244 scope: *Scope,
1104 .force_comptime = gz.force_comptime,1245 rl: ResultLoc,
1105 .instructions = .{},1246 node: ast.Node.Index,
1106 // TODO @as here is working around a stage1 miscompilation bug :(1247 elements: []const ast.Node.Index,
1107 .label = @as(?GenZir.Label, GenZir.Label{1248 result_ptr: Zir.Inst.Ref,
1108 .token = label_token,1249) InnerError!Zir.Inst.Ref {
1109 .block_inst = block_inst,1250 const astgen = gz.astgen;
1110 }),1251 const gpa = astgen.gpa;
1111 };
1112 block_scope.setBreakResultLoc(rl);
1113 defer block_scope.instructions.deinit(mod.gpa);
1114 defer block_scope.labeled_breaks.deinit(mod.gpa);
1115 defer block_scope.labeled_store_to_block_ptr_list.deinit(mod.gpa);
11161252
1117 try blockExprStmts(&block_scope, &block_scope.base, block_node, statements);1253 const elem_ptr_list = try gpa.alloc(Zir.Inst.Index, elements.len);
1254 defer gpa.free(elem_ptr_list);
11181255
1119 if (!block_scope.label.?.used) {1256 for (elements) |elem_init, i| {
1120 return mod.failTok(parent_scope, label_token, "unused block label", .{});1257 const index_inst = try gz.addInt(i);
1258 const elem_ptr = try gz.addPlNode(.elem_ptr_node, elem_init, Zir.Inst.Bin{
1259 .lhs = result_ptr,
1260 .rhs = index_inst,
1261 });
1262 elem_ptr_list[i] = gz.refToIndex(elem_ptr).?;
1263 _ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init);
1121 }1264 }
1265 _ = try gz.addPlNode(.validate_array_init_ptr, node, Zir.Inst.Block{
1266 .body_len = @intCast(u32, elem_ptr_list.len),
1267 });
1268 try astgen.extra.appendSlice(gpa, elem_ptr_list);
1269 return .void_value;
1270}
11221271
1123 const zir_tags = gz.astgen.instructions.items(.tag);1272fn structInitExpr(
1124 const zir_datas = gz.astgen.instructions.items(.data);1273 gz: *GenZir,
1274 scope: *Scope,
1275 rl: ResultLoc,
1276 node: ast.Node.Index,
1277 struct_init: ast.full.StructInit,
1278) InnerError!Zir.Inst.Ref {
1279 const astgen = gz.astgen;
1280 const tree = astgen.tree;
1281 const gpa = astgen.gpa;
11251282
1126 const strat = rl.strategy(&block_scope);1283 if (struct_init.ast.fields.len == 0) {
1127 switch (strat.tag) {1284 if (struct_init.ast.type_expr == 0) {
1128 .break_void => {1285 return rvalue(gz, scope, rl, .empty_struct, node);
1129 // The code took advantage of the result location as a pointer.1286 }
1130 // Turn the break instruction operands into void.1287 array: {
1131 for (block_scope.labeled_breaks.items) |br| {1288 const node_tags = tree.nodes.items(.tag);
1132 zir_datas[br].@"break".operand = .void_value;1289 const main_tokens = tree.nodes.items(.main_token);
1290 const array_type: ast.full.ArrayType = switch (node_tags[struct_init.ast.type_expr]) {
1291 .array_type => tree.arrayType(struct_init.ast.type_expr),
1292 .array_type_sentinel => tree.arrayTypeSentinel(struct_init.ast.type_expr),
1293 else => break :array,
1294 };
1295 // This intentionally does not support `@"_"` syntax.
1296 if (node_tags[array_type.ast.elem_count] == .identifier and
1297 mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_"))
1298 {
1299 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
1300 const array_type_inst = if (array_type.ast.sentinel == 0) blk: {
1301 break :blk try gz.addBin(.array_type, .zero_usize, elem_type);
1302 } else blk: {
1303 const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel);
1304 break :blk try gz.addArrayTypeSentinel(.zero_usize, elem_type, sentinel);
1305 };
1306 const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node);
1307 return rvalue(gz, scope, rl, result, node);
1133 }1308 }
1134 try block_scope.setBlockBody(block_inst);1309 }
11351310 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1136 return gz.astgen.indexToRef(block_inst);1311 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
1312 return rvalue(gz, scope, rl, result, node);
1313 }
1314 switch (rl) {
1315 .discard => {
1316 for (struct_init.ast.fields) |field_init| {
1317 _ = try expr(gz, scope, .discard, field_init);
1318 }
1319 return Zir.Inst.Ref.void_value;
1137 },1320 },
1138 .break_operand => {1321 .ref => {
1139 // All break operands are values that did not use the result location pointer.1322 if (struct_init.ast.type_expr != 0) {
1140 if (strat.elide_store_to_block_ptr_instructions) {1323 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1141 for (block_scope.labeled_store_to_block_ptr_list.items) |inst| {1324 return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst, .struct_init_ref);
1142 zir_tags[inst] = .elided;1325 } else {
1143 zir_datas[inst] = undefined;1326 return structInitExprRlNone(gz, scope, rl, node, struct_init, .struct_init_anon_ref);
1144 }
1145 // TODO technically not needed since we changed the tag to elided but
1146 // would be better still to elide the ones that are in this list.
1147 }1327 }
1148 try block_scope.setBlockBody(block_inst);1328 },
1149 const block_ref = gz.astgen.indexToRef(block_inst);1329 .none, .none_or_ref => {
1150 switch (rl) {1330 if (struct_init.ast.type_expr != 0) {
1151 .ref => return block_ref,1331 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1152 else => return rvalue(gz, parent_scope, rl, block_ref, block_node),1332 return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst, .struct_init);
1333 } else {
1334 return structInitExprRlNone(gz, scope, rl, node, struct_init, .struct_init_anon);
1335 }
1336 },
1337 .ty => |ty_inst| {
1338 if (struct_init.ast.type_expr == 0) {
1339 return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst, .struct_init);
1153 }1340 }
1341 const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1342 const result = try structInitExprRlTy(gz, scope, rl, node, struct_init, inner_ty_inst, .struct_init);
1343 return rvalue(gz, scope, rl, result, node);
1154 },1344 },
1345 .ptr, .inferred_ptr => |ptr_inst| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst),
1346 .block_ptr => |block_gz| return structInitExprRlPtr(gz, scope, rl, node, struct_init, block_gz.rl_ptr),
1155 }1347 }
1156}1348}
11571349
1158fn blockExprStmts(1350fn structInitExprRlNone(
1159 gz: *GenZir,1351 gz: *GenZir,
1160 parent_scope: *Scope,1352 scope: *Scope,
1353 rl: ResultLoc,
1161 node: ast.Node.Index,1354 node: ast.Node.Index,
1162 statements: []const ast.Node.Index,1355 struct_init: ast.full.StructInit,
1163) !void {1356 tag: Zir.Inst.Tag,
1164 const tree = gz.tree();1357) InnerError!Zir.Inst.Ref {
1165 const main_tokens = tree.nodes.items(.main_token);1358 const astgen = gz.astgen;
1166 const node_tags = tree.nodes.items(.tag);1359 const gpa = astgen.gpa;
11671360 const tree = astgen.tree;
1168 var block_arena = std.heap.ArenaAllocator.init(gz.astgen.mod.gpa);
1169 defer block_arena.deinit();
11701361
1171 var scope = parent_scope;1362 const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len);
1172 for (statements) |statement| {1363 defer gpa.free(fields_list);
1173 if (!gz.force_comptime) {
1174 _ = try gz.addNode(.dbg_stmt_node, statement);
1175 }
1176 switch (node_tags[statement]) {
1177 .global_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.globalVarDecl(statement)),
1178 .local_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.localVarDecl(statement)),
1179 .simple_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.simpleVarDecl(statement)),
1180 .aligned_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.alignedVarDecl(statement)),
11811364
1182 .assign => try assign(gz, scope, statement),1365 for (struct_init.ast.fields) |field_init, i| {
1183 .assign_bit_and => try assignOp(gz, scope, statement, .bit_and),1366 const name_token = tree.firstToken(field_init) - 2;
1184 .assign_bit_or => try assignOp(gz, scope, statement, .bit_or),1367 const str_index = try astgen.identAsString(name_token);
1185 .assign_bit_shift_left => try assignOp(gz, scope, statement, .shl),
1186 .assign_bit_shift_right => try assignOp(gz, scope, statement, .shr),
1187 .assign_bit_xor => try assignOp(gz, scope, statement, .xor),
1188 .assign_div => try assignOp(gz, scope, statement, .div),
1189 .assign_sub => try assignOp(gz, scope, statement, .sub),
1190 .assign_sub_wrap => try assignOp(gz, scope, statement, .subwrap),
1191 .assign_mod => try assignOp(gz, scope, statement, .mod_rem),
1192 .assign_add => try assignOp(gz, scope, statement, .add),
1193 .assign_add_wrap => try assignOp(gz, scope, statement, .addwrap),
1194 .assign_mul => try assignOp(gz, scope, statement, .mul),
1195 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),
11961368
1197 else => {1369 fields_list[i] = .{
1198 // We need to emit an error if the result is not `noreturn` or `void`, but1370 .field_name = str_index,
1199 // we want to avoid adding the ZIR instruction if possible for performance.1371 .init = try expr(gz, scope, .none, field_init),
1200 const maybe_unused_result = try expr(gz, scope, .none, statement);1372 };
1201 const elide_check = if (gz.astgen.refToIndex(maybe_unused_result)) |inst| b: {1373 }
1202 // Note that this array becomes invalid after appending more items to it1374 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInitAnon{
1203 // in the above while loop.1375 .fields_len = @intCast(u32, fields_list.len),
1204 const zir_tags = gz.astgen.instructions.items(.tag);1376 });
1205 switch (zir_tags[inst]) {1377 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
1206 // For some instructions, swap in a slightly different ZIR tag1378 fields_list.len * @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len);
1207 // so we can avoid a separate ensure_result_used instruction.1379 for (fields_list) |field| {
1208 .call_none_chkused => unreachable,1380 _ = gz.astgen.addExtraAssumeCapacity(field);
1209 .call_none => {1381 }
1210 zir_tags[inst] = .call_none_chkused;1382 return init_inst;
1211 break :b true;1383}
1212 },
1213 .call_chkused => unreachable,
1214 .call => {
1215 zir_tags[inst] = .call_chkused;
1216 break :b true;
1217 },
12181384
1219 // ZIR instructions that might be a type other than `noreturn` or `void`.1385fn structInitExprRlPtr(
1220 .add,1386 gz: *GenZir,
1221 .addwrap,1387 scope: *Scope,
1222 .alloc,1388 rl: ResultLoc,
1223 .alloc_mut,1389 node: ast.Node.Index,
1224 .alloc_inferred,1390 struct_init: ast.full.StructInit,
1225 .alloc_inferred_mut,1391 result_ptr: Zir.Inst.Ref,
1226 .array_cat,1392) InnerError!Zir.Inst.Ref {
1227 .array_mul,1393 const astgen = gz.astgen;
1228 .array_type,1394 const gpa = astgen.gpa;
1229 .array_type_sentinel,1395 const tree = astgen.tree;
1230 .indexable_ptr_len,
1231 .as,
1232 .as_node,
1233 .@"asm",
1234 .asm_volatile,
1235 .bit_and,
1236 .bitcast,
1237 .bitcast_result_ptr,
1238 .bit_or,
1239 .block,
1240 .block_inline,
1241 .loop,
1242 .bool_br_and,
1243 .bool_br_or,
1244 .bool_not,
1245 .bool_and,
1246 .bool_or,
1247 .call_compile_time,
1248 .cmp_lt,
1249 .cmp_lte,
1250 .cmp_eq,
1251 .cmp_gte,
1252 .cmp_gt,
1253 .cmp_neq,
1254 .coerce_result_ptr,
1255 .decl_ref,
1256 .decl_val,
1257 .load,
1258 .div,
1259 .elem_ptr,
1260 .elem_val,
1261 .elem_ptr_node,
1262 .elem_val_node,
1263 .floatcast,
1264 .field_ptr,
1265 .field_val,
1266 .field_ptr_named,
1267 .field_val_named,
1268 .fn_type,
1269 .fn_type_var_args,
1270 .fn_type_cc,
1271 .fn_type_cc_var_args,
1272 .has_decl,
1273 .int,
1274 .float,
1275 .float128,
1276 .intcast,
1277 .int_type,
1278 .is_non_null,
1279 .is_null,
1280 .is_non_null_ptr,
1281 .is_null_ptr,
1282 .is_err,
1283 .is_err_ptr,
1284 .mod_rem,
1285 .mul,
1286 .mulwrap,
1287 .param_type,
1288 .ptrtoint,
1289 .ref,
1290 .ret_ptr,
1291 .ret_type,
1292 .shl,
1293 .shr,
1294 .str,
1295 .sub,
1296 .subwrap,
1297 .negate,
1298 .negate_wrap,
1299 .typeof,
1300 .typeof_elem,
1301 .xor,
1302 .optional_type,
1303 .optional_type_from_ptr_elem,
1304 .optional_payload_safe,
1305 .optional_payload_unsafe,
1306 .optional_payload_safe_ptr,
1307 .optional_payload_unsafe_ptr,
1308 .err_union_payload_safe,
1309 .err_union_payload_unsafe,
1310 .err_union_payload_safe_ptr,
1311 .err_union_payload_unsafe_ptr,
1312 .err_union_code,
1313 .err_union_code_ptr,
1314 .ptr_type,
1315 .ptr_type_simple,
1316 .enum_literal,
1317 .enum_literal_small,
1318 .merge_error_sets,
1319 .error_union_type,
1320 .bit_not,
1321 .error_value,
1322 .error_to_int,
1323 .int_to_error,
1324 .slice_start,
1325 .slice_end,
1326 .slice_sentinel,
1327 .import,
1328 .typeof_peer,
1329 .switch_block,
1330 .switch_block_multi,
1331 .switch_block_else,
1332 .switch_block_else_multi,
1333 .switch_block_under,
1334 .switch_block_under_multi,
1335 .switch_block_ref,
1336 .switch_block_ref_multi,
1337 .switch_block_ref_else,
1338 .switch_block_ref_else_multi,
1339 .switch_block_ref_under,
1340 .switch_block_ref_under_multi,
1341 .switch_capture,
1342 .switch_capture_ref,
1343 .switch_capture_multi,
1344 .switch_capture_multi_ref,
1345 .switch_capture_else,
1346 .switch_capture_else_ref,
1347 .struct_init_empty,
1348 .struct_init,
1349 .field_type,
1350 .struct_decl,
1351 .struct_decl_packed,
1352 .struct_decl_extern,
1353 .union_decl,
1354 .enum_decl,
1355 .enum_decl_nonexhaustive,
1356 .opaque_decl,
1357 .int_to_enum,
1358 .enum_to_int,
1359 .type_info,
1360 => break :b false,
1361
1362 // ZIR instructions that are always either `noreturn` or `void`.
1363 .breakpoint,
1364 .dbg_stmt_node,
1365 .ensure_result_used,
1366 .ensure_result_non_error,
1367 .@"export",
1368 .set_eval_branch_quota,
1369 .compile_log,
1370 .ensure_err_payload_void,
1371 .@"break",
1372 .break_inline,
1373 .condbr,
1374 .condbr_inline,
1375 .compile_error,
1376 .ret_node,
1377 .ret_tok,
1378 .ret_coerce,
1379 .@"unreachable",
1380 .elided,
1381 .store,
1382 .store_node,
1383 .store_to_block_ptr,
1384 .store_to_inferred_ptr,
1385 .resolve_inferred_alloc,
1386 .repeat,
1387 .repeat_inline,
1388 .validate_struct_init_ptr,
1389 => break :b true,
1390 }
1391 } else switch (maybe_unused_result) {
1392 .none => unreachable,
13931396
1394 .void_value,1397 const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len);
1395 .unreachable_value,1398 defer gpa.free(field_ptr_list);
1396 => true,
13971399
1398 else => false,1400 for (struct_init.ast.fields) |field_init, i| {
1399 };1401 const name_token = tree.firstToken(field_init) - 2;
1400 if (!elide_check) {1402 const str_index = try astgen.identAsString(name_token);
1401 _ = try gz.addUnNode(.ensure_result_used, maybe_unused_result, statement);1403 const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{
1402 }1404 .lhs = result_ptr,
1403 },1405 .field_name_start = str_index,
1404 }1406 });
1407 field_ptr_list[i] = gz.refToIndex(field_ptr).?;
1408 _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init);
1405 }1409 }
1410 _ = try gz.addPlNode(.validate_struct_init_ptr, node, Zir.Inst.Block{
1411 .body_len = @intCast(u32, field_ptr_list.len),
1412 });
1413 try astgen.extra.appendSlice(gpa, field_ptr_list);
1414 return .void_value;
1406}1415}
14071416
1408fn varDecl(1417fn structInitExprRlTy(
1409 gz: *GenZir,1418 gz: *GenZir,
1410 scope: *Scope,1419 scope: *Scope,
1420 rl: ResultLoc,
1411 node: ast.Node.Index,1421 node: ast.Node.Index,
1412 block_arena: *Allocator,1422 struct_init: ast.full.StructInit,
1413 var_decl: ast.full.VarDecl,1423 ty_inst: Zir.Inst.Ref,
1414) InnerError!*Scope {1424 tag: Zir.Inst.Tag,
1415 const mod = gz.astgen.mod;1425) InnerError!Zir.Inst.Ref {
1416 if (var_decl.comptime_token) |comptime_token| {
1417 return mod.failTok(scope, comptime_token, "TODO implement comptime locals", .{});
1418 }
1419 if (var_decl.ast.align_node != 0) {
1420 return mod.failNode(scope, var_decl.ast.align_node, "TODO implement alignment on locals", .{});
1421 }
1422 const astgen = gz.astgen;1426 const astgen = gz.astgen;
1423 const tree = gz.tree();1427 const gpa = astgen.gpa;
1424 const token_tags = tree.tokens.items(.tag);1428 const tree = astgen.tree;
14251429
1426 const name_token = var_decl.ast.mut_token + 1;1430 const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len);
1427 const name_src = gz.tokSrcLoc(name_token);1431 defer gpa.free(fields_list);
1428 const ident_name = try mod.identifierTokenString(scope, name_token);
14291432
1430 // Local variables shadowing detection, including function parameters.1433 for (struct_init.ast.fields) |field_init, i| {
1431 {1434 const name_token = tree.firstToken(field_init) - 2;
1432 var s = scope;1435 const str_index = try astgen.identAsString(name_token);
1433 while (true) switch (s.tag) {
1434 .local_val => {
1435 const local_val = s.cast(Scope.LocalVal).?;
1436 if (mem.eql(u8, local_val.name, ident_name)) {
1437 const msg = msg: {
1438 const msg = try mod.errMsg(scope, name_src, "redefinition of '{s}'", .{
1439 ident_name,
1440 });
1441 errdefer msg.destroy(mod.gpa);
1442 try mod.errNote(scope, local_val.src, msg, "previous definition is here", .{});
1443 break :msg msg;
1444 };
1445 return mod.failWithOwnedErrorMsg(scope, msg);
1446 }
1447 s = local_val.parent;
1448 },
1449 .local_ptr => {
1450 const local_ptr = s.cast(Scope.LocalPtr).?;
1451 if (mem.eql(u8, local_ptr.name, ident_name)) {
1452 const msg = msg: {
1453 const msg = try mod.errMsg(scope, name_src, "redefinition of '{s}'", .{
1454 ident_name,
1455 });
1456 errdefer msg.destroy(mod.gpa);
1457 try mod.errNote(scope, local_ptr.src, msg, "previous definition is here", .{});
1458 break :msg msg;
1459 };
1460 return mod.failWithOwnedErrorMsg(scope, msg);
1461 }
1462 s = local_ptr.parent;
1463 },
1464 .gen_zir => s = s.cast(GenZir).?.parent,
1465 else => break,
1466 };
1467 }
14681436
1469 // Namespace vars shadowing detection1437 const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{
1470 if (mod.lookupDeclName(scope, ident_name)) |_| {1438 .container_type = ty_inst,
1471 // TODO add note for other definition1439 .name_start = str_index,
1472 return mod.fail(scope, name_src, "redefinition of '{s}'", .{ident_name});1440 });
1441 fields_list[i] = .{
1442 .field_type = gz.refToIndex(field_ty_inst).?,
1443 .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init),
1444 };
1473 }1445 }
1474 if (var_decl.ast.init_node == 0) {1446 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInit{
1475 return mod.fail(scope, name_src, "variables must be initialized", .{});1447 .fields_len = @intCast(u32, fields_list.len),
1448 });
1449 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
1450 fields_list.len * @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len);
1451 for (fields_list) |field| {
1452 _ = gz.astgen.addExtraAssumeCapacity(field);
1476 }1453 }
1454 return init_inst;
1455}
14771456
1478 switch (token_tags[var_decl.ast.mut_token]) {1457/// This calls expr in a comptime scope, and is intended to be called as a helper function.
1479 .keyword_const => {1458/// The one that corresponds to `comptime` expression syntax is `comptimeExprAst`.
1480 // Depending on the type of AST the initialization expression is, we may need an lvalue1459fn comptimeExpr(
1481 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as1460 gz: *GenZir,
1482 // the variable, no memory location needed.1461 scope: *Scope,
1483 if (!nodeMayNeedMemoryLocation(tree, var_decl.ast.init_node)) {1462 rl: ResultLoc,
1484 const result_loc: ResultLoc = if (var_decl.ast.type_node != 0) .{1463 node: ast.Node.Index,
1485 .ty = try typeExpr(gz, scope, var_decl.ast.type_node),1464) InnerError!Zir.Inst.Ref {
1486 } else .none;1465 const prev_force_comptime = gz.force_comptime;
1487 const init_inst = try expr(gz, scope, result_loc, var_decl.ast.init_node);1466 gz.force_comptime = true;
1488 const sub_scope = try block_arena.create(Scope.LocalVal);1467 const result = try expr(gz, scope, rl, node);
1489 sub_scope.* = .{1468 gz.force_comptime = prev_force_comptime;
1490 .parent = scope,1469 return result;
1491 .gen_zir = gz,1470}
1492 .name = ident_name,
1493 .inst = init_inst,
1494 .src = name_src,
1495 };
1496 return &sub_scope.base;
1497 }
14981471
1499 // Detect whether the initialization expression actually uses the1472/// This one is for an actual `comptime` syntax, and will emit a compile error if
1500 // result location pointer.1473/// the scope already has `force_comptime=true`.
1501 var init_scope: GenZir = .{1474/// See `comptimeExpr` for the helper function for calling expr in a comptime scope.
1502 .parent = scope,1475fn comptimeExprAst(
1503 .force_comptime = gz.force_comptime,1476 gz: *GenZir,
1504 .astgen = astgen,1477 scope: *Scope,
1505 };1478 rl: ResultLoc,
1506 defer init_scope.instructions.deinit(mod.gpa);1479 node: ast.Node.Index,
1480) InnerError!Zir.Inst.Ref {
1481 const astgen = gz.astgen;
1482 if (gz.force_comptime) {
1483 return astgen.failNode(node, "redundant comptime keyword in already comptime scope", .{});
1484 }
1485 const tree = astgen.tree;
1486 const node_datas = tree.nodes.items(.data);
1487 const body_node = node_datas[node].lhs;
1488 gz.force_comptime = true;
1489 const result = try expr(gz, scope, rl, body_node);
1490 gz.force_comptime = false;
1491 return result;
1492}
15071493
1508 var resolve_inferred_alloc: zir.Inst.Ref = .none;1494fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
1509 var opt_type_inst: zir.Inst.Ref = .none;1495 const astgen = parent_gz.astgen;
1510 if (var_decl.ast.type_node != 0) {1496 const tree = astgen.tree;
1511 const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node);1497 const node_datas = tree.nodes.items(.data);
1512 opt_type_inst = type_inst;1498 const break_label = node_datas[node].lhs;
1513 init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node);1499 const rhs = node_datas[node].rhs;
1514 init_scope.rl_ty_inst = type_inst;
1515 } else {
1516 const alloc = try init_scope.addNode(.alloc_inferred, node);
1517 resolve_inferred_alloc = alloc;
1518 init_scope.rl_ptr = alloc;
1519 }
1520 const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope };
1521 const init_inst = try expr(&init_scope, &init_scope.base, init_result_loc, var_decl.ast.init_node);
1522 const zir_tags = astgen.instructions.items(.tag);
1523 const zir_datas = astgen.instructions.items(.data);
15241500
1525 const parent_zir = &gz.instructions;1501 // Look for the label in the scope.
1526 if (init_scope.rvalue_rl_count == 1) {1502 var scope = parent_scope;
1527 // Result location pointer not used. We don't need an alloc for this1503 while (true) {
1528 // const local, and type inference becomes trivial.1504 switch (scope.tag) {
1529 // Move the init_scope instructions into the parent scope, eliding1505 .gen_zir => {
1530 // the alloc instruction and the store_to_block_ptr instruction.1506 const block_gz = scope.cast(GenZir).?;
1531 const expected_len = parent_zir.items.len + init_scope.instructions.items.len - 2;1507
1532 try parent_zir.ensureCapacity(mod.gpa, expected_len);1508 const block_inst = blk: {
1533 for (init_scope.instructions.items) |src_inst| {1509 if (break_label != 0) {
1534 if (astgen.indexToRef(src_inst) == init_scope.rl_ptr) continue;1510 if (block_gz.label) |*label| {
1535 if (zir_tags[src_inst] == .store_to_block_ptr) {1511 if (try astgen.tokenIdentEql(label.token, break_label)) {
1536 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue;1512 label.used = true;
1513 break :blk label.block_inst;
1514 }
1515 }
1516 } else if (block_gz.break_block != 0) {
1517 break :blk block_gz.break_block;
1537 }1518 }
1538 parent_zir.appendAssumeCapacity(src_inst);1519 scope = block_gz.parent;
1520 continue;
1521 };
1522
1523 if (rhs == 0) {
1524 _ = try parent_gz.addBreak(.@"break", block_inst, .void_value);
1525 return Zir.Inst.Ref.unreachable_value;
1539 }1526 }
1540 assert(parent_zir.items.len == expected_len);1527 block_gz.break_count += 1;
1528 const prev_rvalue_rl_count = block_gz.rvalue_rl_count;
1529 const operand = try expr(parent_gz, parent_scope, block_gz.break_result_loc, rhs);
1530 const have_store_to_block = block_gz.rvalue_rl_count != prev_rvalue_rl_count;
15411531
1542 const sub_scope = try block_arena.create(Scope.LocalVal);1532 const br = try parent_gz.addBreak(.@"break", block_inst, operand);
1543 sub_scope.* = .{1533
1544 .parent = scope,1534 if (block_gz.break_result_loc == .block_ptr) {
1545 .gen_zir = gz,1535 try block_gz.labeled_breaks.append(astgen.gpa, br);
1546 .name = ident_name,1536
1547 .inst = init_inst,1537 if (have_store_to_block) {
1548 .src = name_src,1538 const zir_tags = parent_gz.astgen.instructions.items(.tag);
1549 };1539 const zir_datas = parent_gz.astgen.instructions.items(.data);
1550 return &sub_scope.base;1540 const store_inst = @intCast(u32, zir_tags.len - 2);
1551 }1541 assert(zir_tags[store_inst] == .store_to_block_ptr);
1552 // The initialization expression took advantage of the result location1542 assert(zir_datas[store_inst].bin.lhs == block_gz.rl_ptr);
1553 // of the const local. In this case we will create an alloc and a LocalPtr for it.1543 try block_gz.labeled_store_to_block_ptr_list.append(astgen.gpa, store_inst);
1554 // Move the init_scope instructions into the parent scope, swapping
1555 // store_to_block_ptr for store_to_inferred_ptr.
1556 const expected_len = parent_zir.items.len + init_scope.instructions.items.len;
1557 try parent_zir.ensureCapacity(mod.gpa, expected_len);
1558 for (init_scope.instructions.items) |src_inst| {
1559 if (zir_tags[src_inst] == .store_to_block_ptr) {
1560 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) {
1561 zir_tags[src_inst] = .store_to_inferred_ptr;
1562 }1544 }
1563 }1545 }
1564 parent_zir.appendAssumeCapacity(src_inst);1546 return Zir.Inst.Ref.unreachable_value;
1565 }1547 },
1566 assert(parent_zir.items.len == expected_len);1548 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
1567 if (resolve_inferred_alloc != .none) {1549 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1568 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);1550 .namespace => break,
1569 }1551 .defer_normal => {
1570 const sub_scope = try block_arena.create(Scope.LocalPtr);1552 const defer_scope = scope.cast(Scope.Defer).?;
1571 sub_scope.* = .{1553 scope = defer_scope.parent;
1572 .parent = scope,1554 const expr_node = node_datas[defer_scope.defer_node].rhs;
1573 .gen_zir = gz,1555 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
1574 .name = ident_name,1556 },
1575 .ptr = init_scope.rl_ptr,1557 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1576 .src = name_src,1558 .top => unreachable,
1577 };1559 }
1578 return &sub_scope.base;1560 }
1579 },1561 if (break_label != 0) {
1580 .keyword_var => {1562 const label_name = try astgen.identifierTokenString(break_label);
1581 var resolve_inferred_alloc: zir.Inst.Ref = .none;1563 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
1582 const var_data: struct {1564 } else {
1583 result_loc: ResultLoc,1565 return astgen.failNode(node, "break expression outside loop", .{});
1584 alloc: zir.Inst.Ref,
1585 } = if (var_decl.ast.type_node != 0) a: {
1586 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);
1587
1588 const alloc = try gz.addUnNode(.alloc_mut, type_inst, node);
1589 break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } };
1590 } else a: {
1591 const alloc = try gz.addNode(.alloc_inferred_mut, node);
1592 resolve_inferred_alloc = alloc;
1593 break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } };
1594 };
1595 const init_inst = try expr(gz, scope, var_data.result_loc, var_decl.ast.init_node);
1596 if (resolve_inferred_alloc != .none) {
1597 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
1598 }
1599 const sub_scope = try block_arena.create(Scope.LocalPtr);
1600 sub_scope.* = .{
1601 .parent = scope,
1602 .gen_zir = gz,
1603 .name = ident_name,
1604 .ptr = var_data.alloc,
1605 .src = name_src,
1606 };
1607 return &sub_scope.base;
1608 },
1609 else => unreachable,
1610 }1566 }
1611}1567}
16121568
1613fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {1569fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
1614 const tree = gz.tree();1570 const astgen = parent_gz.astgen;
1571 const tree = astgen.tree;
1615 const node_datas = tree.nodes.items(.data);1572 const node_datas = tree.nodes.items(.data);
1616 const main_tokens = tree.nodes.items(.main_token);1573 const break_label = node_datas[node].lhs;
1617 const node_tags = tree.nodes.items(.tag);
16181574
1619 const lhs = node_datas[infix_node].lhs;1575 // Look for the label in the scope.
1620 const rhs = node_datas[infix_node].rhs;1576 var scope = parent_scope;
1621 if (node_tags[lhs] == .identifier) {1577 while (true) {
1622 // This intentionally does not support `@"_"` syntax.1578 switch (scope.tag) {
1623 const ident_name = tree.tokenSlice(main_tokens[lhs]);1579 .gen_zir => {
1624 if (mem.eql(u8, ident_name, "_")) {1580 const gen_zir = scope.cast(GenZir).?;
1625 _ = try expr(gz, scope, .discard, rhs);1581 const continue_block = gen_zir.continue_block;
1626 return;1582 if (continue_block == 0) {
1583 scope = gen_zir.parent;
1584 continue;
1585 }
1586 if (break_label != 0) blk: {
1587 if (gen_zir.label) |*label| {
1588 if (try astgen.tokenIdentEql(label.token, break_label)) {
1589 label.used = true;
1590 break :blk;
1591 }
1592 }
1593 // found continue but either it has a different label, or no label
1594 scope = gen_zir.parent;
1595 continue;
1596 }
1597
1598 // TODO emit a break_inline if the loop being continued is inline
1599 _ = try parent_gz.addBreak(.@"break", continue_block, .void_value);
1600 return Zir.Inst.Ref.unreachable_value;
1601 },
1602 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
1603 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1604 .defer_normal => {
1605 const defer_scope = scope.cast(Scope.Defer).?;
1606 scope = defer_scope.parent;
1607 const expr_node = node_datas[defer_scope.defer_node].rhs;
1608 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
1609 },
1610 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1611 .namespace => break,
1612 .top => unreachable,
1627 }1613 }
1628 }1614 }
1629 const lvalue = try lvalExpr(gz, scope, lhs);1615 if (break_label != 0) {
1630 _ = try expr(gz, scope, .{ .ptr = lvalue }, rhs);1616 const label_name = try astgen.identifierTokenString(break_label);
1617 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
1618 } else {
1619 return astgen.failNode(node, "continue expression outside loop", .{});
1620 }
1631}1621}
16321622
1633fn assignOp(1623fn blockExpr(
1634 gz: *GenZir,1624 gz: *GenZir,
1635 scope: *Scope,1625 scope: *Scope,
1636 infix_node: ast.Node.Index,1626 rl: ResultLoc,
1637 op_inst_tag: zir.Inst.Tag,1627 block_node: ast.Node.Index,
1638) InnerError!void {1628 statements: []const ast.Node.Index,
1639 const tree = gz.tree();1629) InnerError!Zir.Inst.Ref {
1640 const node_datas = tree.nodes.items(.data);1630 const tracy = trace(@src());
16411631 defer tracy.end();
1642 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
1643 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
1644 const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node);
1645 const rhs = try expr(gz, scope, .{ .ty = lhs_type }, node_datas[infix_node].rhs);
16461632
1647 const result = try gz.addPlNode(op_inst_tag, infix_node, zir.Inst.Bin{1633 const astgen = gz.astgen;
1648 .lhs = lhs,1634 const tree = astgen.tree;
1649 .rhs = rhs,1635 const main_tokens = tree.nodes.items(.main_token);
1650 });1636 const token_tags = tree.tokens.items(.tag);
1651 _ = try gz.addBin(.store, lhs_ptr, result);
1652}
16531637
1654fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref {1638 const lbrace = main_tokens[block_node];
1655 const tree = gz.tree();1639 if (token_tags[lbrace - 1] == .colon and
1656 const node_datas = tree.nodes.items(.data);1640 token_tags[lbrace - 2] == .identifier)
1641 {
1642 return labeledBlockExpr(gz, scope, rl, block_node, statements, .block);
1643 }
16571644
1658 const operand = try expr(gz, scope, .{ .ty = .bool_type }, node_datas[node].lhs);1645 try blockExprStmts(gz, scope, block_node, statements);
1659 const result = try gz.addUnNode(.bool_not, operand, node);1646 return rvalue(gz, scope, rl, .void_value, block_node);
1660 return rvalue(gz, scope, rl, result, node);
1661}1647}
16621648
1663fn bitNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref {1649fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: ast.TokenIndex) !void {
1664 const tree = gz.tree();1650 // Look for the label in the scope.
1665 const node_datas = tree.nodes.items(.data);1651 var scope = parent_scope;
1652 while (true) {
1653 switch (scope.tag) {
1654 .gen_zir => {
1655 const gen_zir = scope.cast(GenZir).?;
1656 if (gen_zir.label) |prev_label| {
1657 if (try astgen.tokenIdentEql(label, prev_label.token)) {
1658 const tree = astgen.tree;
1659 const main_tokens = tree.nodes.items(.main_token);
16661660
1667 const operand = try expr(gz, scope, .none, node_datas[node].lhs);1661 const label_name = try astgen.identifierTokenString(label);
1668 const result = try gz.addUnNode(.bit_not, operand, node);1662 return astgen.failTokNotes(label, "redefinition of label '{s}'", .{
1669 return rvalue(gz, scope, rl, result, node);1663 label_name,
1664 }, &[_]u32{
1665 try astgen.errNoteTok(
1666 prev_label.token,
1667 "previous definition is here",
1668 .{},
1669 ),
1670 });
1671 }
1672 }
1673 scope = gen_zir.parent;
1674 },
1675 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
1676 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1677 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1678 .namespace => break,
1679 .top => unreachable,
1680 }
1681 }
1670}1682}
16711683
1672fn negation(1684fn labeledBlockExpr(
1673 gz: *GenZir,1685 gz: *GenZir,
1674 scope: *Scope,1686 parent_scope: *Scope,
1675 rl: ResultLoc,1687 rl: ResultLoc,
1676 node: ast.Node.Index,1688 block_node: ast.Node.Index,
1677 tag: zir.Inst.Tag,1689 statements: []const ast.Node.Index,
1678) InnerError!zir.Inst.Ref {1690 zir_tag: Zir.Inst.Tag,
1679 const tree = gz.tree();1691) InnerError!Zir.Inst.Ref {
1680 const node_datas = tree.nodes.items(.data);1692 const tracy = trace(@src());
1693 defer tracy.end();
16811694
1682 const operand = try expr(gz, scope, .none, node_datas[node].lhs);1695 assert(zir_tag == .block);
1683 const result = try gz.addUnNode(tag, operand, node);
1684 return rvalue(gz, scope, rl, result, node);
1685}
16861696
1687fn ptrType(1697 const astgen = gz.astgen;
1688 gz: *GenZir,1698 const tree = astgen.tree;
1689 scope: *Scope,1699 const main_tokens = tree.nodes.items(.main_token);
1690 rl: ResultLoc,1700 const token_tags = tree.tokens.items(.tag);
1691 node: ast.Node.Index,
1692 ptr_info: ast.full.PtrType,
1693) InnerError!zir.Inst.Ref {
1694 const tree = gz.tree();
16951701
1696 const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type);1702 const lbrace = main_tokens[block_node];
1703 const label_token = lbrace - 2;
1704 assert(token_tags[label_token] == .identifier);
16971705
1698 const simple = ptr_info.ast.align_node == 0 and1706 try astgen.checkLabelRedefinition(parent_scope, label_token);
1699 ptr_info.ast.sentinel == 0 and
1700 ptr_info.ast.bit_range_start == 0;
17011707
1702 if (simple) {1708 // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct
1703 const result = try gz.add(.{ .tag = .ptr_type_simple, .data = .{1709 // so that break statements can reference it.
1704 .ptr_type_simple = .{1710 const block_inst = try gz.addBlock(zir_tag, block_node);
1705 .is_allowzero = ptr_info.allowzero_token != null,1711 try gz.instructions.append(astgen.gpa, block_inst);
1706 .is_mutable = ptr_info.const_token == null,
1707 .is_volatile = ptr_info.volatile_token != null,
1708 .size = ptr_info.size,
1709 .elem_type = elem_type,
1710 },
1711 } });
1712 return rvalue(gz, scope, rl, result, node);
1713 }
17141712
1715 var sentinel_ref: zir.Inst.Ref = .none;1713 var block_scope = gz.makeSubBlock(parent_scope);
1716 var align_ref: zir.Inst.Ref = .none;1714 block_scope.label = GenZir.Label{
1717 var bit_start_ref: zir.Inst.Ref = .none;1715 .token = label_token,
1718 var bit_end_ref: zir.Inst.Ref = .none;1716 .block_inst = block_inst,
1719 var trailing_count: u32 = 0;1717 };
1718 block_scope.setBreakResultLoc(rl);
1719 defer block_scope.instructions.deinit(astgen.gpa);
1720 defer block_scope.labeled_breaks.deinit(astgen.gpa);
1721 defer block_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);
17201722
1721 if (ptr_info.ast.sentinel != 0) {1723 try blockExprStmts(&block_scope, &block_scope.base, block_node, statements);
1722 sentinel_ref = try expr(gz, scope, .{ .ty = elem_type }, ptr_info.ast.sentinel);1724
1723 trailing_count += 1;1725 if (!block_scope.label.?.used) {
1724 }1726 return astgen.failTok(label_token, "unused block label", .{});
1725 if (ptr_info.ast.align_node != 0) {
1726 align_ref = try expr(gz, scope, .none, ptr_info.ast.align_node);
1727 trailing_count += 1;
1728 }
1729 if (ptr_info.ast.bit_range_start != 0) {
1730 assert(ptr_info.ast.bit_range_end != 0);
1731 bit_start_ref = try expr(gz, scope, .none, ptr_info.ast.bit_range_start);
1732 bit_end_ref = try expr(gz, scope, .none, ptr_info.ast.bit_range_end);
1733 trailing_count += 2;
1734 }1727 }
17351728
1736 const gpa = gz.astgen.mod.gpa;1729 const zir_tags = gz.astgen.instructions.items(.tag);
1737 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);1730 const zir_datas = gz.astgen.instructions.items(.data);
1738 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1739 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
1740 @typeInfo(zir.Inst.PtrType).Struct.fields.len + trailing_count);
17411731
1742 const payload_index = gz.astgen.addExtraAssumeCapacity(zir.Inst.PtrType{ .elem_type = elem_type });1732 const strat = rl.strategy(&block_scope);
1743 if (sentinel_ref != .none) {1733 switch (strat.tag) {
1744 gz.astgen.extra.appendAssumeCapacity(@enumToInt(sentinel_ref));1734 .break_void => {
1745 }1735 // The code took advantage of the result location as a pointer.
1746 if (align_ref != .none) {1736 // Turn the break instruction operands into void.
1747 gz.astgen.extra.appendAssumeCapacity(@enumToInt(align_ref));1737 for (block_scope.labeled_breaks.items) |br| {
1748 }1738 zir_datas[br].@"break".operand = .void_value;
1749 if (bit_start_ref != .none) {1739 }
1750 gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_start_ref));1740 try block_scope.setBlockBody(block_inst);
1751 gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_end_ref));
1752 }
17531741
1754 const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);1742 return gz.indexToRef(block_inst);
1755 const result = gz.astgen.indexToRef(new_index);
1756 gz.astgen.instructions.appendAssumeCapacity(.{ .tag = .ptr_type, .data = .{
1757 .ptr_type = .{
1758 .flags = .{
1759 .is_allowzero = ptr_info.allowzero_token != null,
1760 .is_mutable = ptr_info.const_token == null,
1761 .is_volatile = ptr_info.volatile_token != null,
1762 .has_sentinel = sentinel_ref != .none,
1763 .has_align = align_ref != .none,
1764 .has_bit_range = bit_start_ref != .none,
1765 },
1766 .size = ptr_info.size,
1767 .payload_index = payload_index,
1768 },1743 },
1769 } });1744 .break_operand => {
1770 gz.instructions.appendAssumeCapacity(new_index);1745 // All break operands are values that did not use the result location pointer.
1746 if (strat.elide_store_to_block_ptr_instructions) {
1747 for (block_scope.labeled_store_to_block_ptr_list.items) |inst| {
1748 // Mark as elided for removal below.
1749 assert(zir_tags[inst] == .store_to_block_ptr);
1750 zir_datas[inst].bin.lhs = .none;
1751 }
1752 try block_scope.setBlockBodyEliding(block_inst);
1753 } else {
1754 try block_scope.setBlockBody(block_inst);
1755 }
1756 const block_ref = gz.indexToRef(block_inst);
1757 switch (rl) {
1758 .ref => return block_ref,
1759 else => return rvalue(gz, parent_scope, rl, block_ref, block_node),
1760 }
1761 },
1762 }
1763}
17711764
1772 return rvalue(gz, scope, rl, result, node);1765fn blockExprStmts(
1766 gz: *GenZir,
1767 parent_scope: *Scope,
1768 node: ast.Node.Index,
1769 statements: []const ast.Node.Index,
1770) !void {
1771 const astgen = gz.astgen;
1772 const tree = astgen.tree;
1773 const main_tokens = tree.nodes.items(.main_token);
1774 const node_tags = tree.nodes.items(.tag);
1775
1776 var block_arena = std.heap.ArenaAllocator.init(gz.astgen.gpa);
1777 defer block_arena.deinit();
1778
1779 var scope = parent_scope;
1780 for (statements) |statement| {
1781 switch (node_tags[statement]) {
1782 // zig fmt: off
1783 .global_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.globalVarDecl(statement)),
1784 .local_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.localVarDecl(statement)),
1785 .simple_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.simpleVarDecl(statement)),
1786 .aligned_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.alignedVarDecl(statement)),
1787
1788 .@"defer" => scope = try deferStmt(gz, scope, statement, &block_arena.allocator, .defer_normal),
1789 .@"errdefer" => scope = try deferStmt(gz, scope, statement, &block_arena.allocator, .defer_error),
1790
1791 .assign => try assign(gz, scope, statement),
1792
1793 .assign_bit_shift_left => try assignShift(gz, scope, statement, .shl),
1794 .assign_bit_shift_right => try assignShift(gz, scope, statement, .shr),
1795
1796 .assign_bit_and => try assignOp(gz, scope, statement, .bit_and),
1797 .assign_bit_or => try assignOp(gz, scope, statement, .bit_or),
1798 .assign_bit_xor => try assignOp(gz, scope, statement, .xor),
1799 .assign_div => try assignOp(gz, scope, statement, .div),
1800 .assign_sub => try assignOp(gz, scope, statement, .sub),
1801 .assign_sub_wrap => try assignOp(gz, scope, statement, .subwrap),
1802 .assign_mod => try assignOp(gz, scope, statement, .mod_rem),
1803 .assign_add => try assignOp(gz, scope, statement, .add),
1804 .assign_add_wrap => try assignOp(gz, scope, statement, .addwrap),
1805 .assign_mul => try assignOp(gz, scope, statement, .mul),
1806 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),
1807
1808 else => try unusedResultExpr(gz, scope, statement),
1809 // zig fmt: on
1810 }
1811 }
1812
1813 try genDefers(gz, parent_scope, scope, .none);
1773}1814}
17741815
1775fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !zir.Inst.Ref {1816fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) InnerError!void {
1776 const tree = gz.tree();1817 try emitDbgNode(gz, statement);
1777 const node_datas = tree.nodes.items(.data);1818 // We need to emit an error if the result is not `noreturn` or `void`, but
1819 // we want to avoid adding the ZIR instruction if possible for performance.
1820 const maybe_unused_result = try expr(gz, scope, .none, statement);
1821 const elide_check = if (gz.refToIndex(maybe_unused_result)) |inst| b: {
1822 // Note that this array becomes invalid after appending more items to it
1823 // in the above while loop.
1824 const zir_tags = gz.astgen.instructions.items(.tag);
1825 switch (zir_tags[inst]) {
1826 // For some instructions, swap in a slightly different ZIR tag
1827 // so we can avoid a separate ensure_result_used instruction.
1828 .call_chkused => unreachable,
1829 .call => {
1830 zir_tags[inst] = .call_chkused;
1831 break :b true;
1832 },
17781833
1779 // TODO check for [_]T1834 // ZIR instructions that might be a type other than `noreturn` or `void`.
1780 const len = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].lhs);1835 .add,
1781 const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);1836 .addwrap,
1837 .arg,
1838 .alloc,
1839 .alloc_mut,
1840 .alloc_comptime,
1841 .alloc_inferred,
1842 .alloc_inferred_mut,
1843 .alloc_inferred_comptime,
1844 .array_cat,
1845 .array_mul,
1846 .array_type,
1847 .array_type_sentinel,
1848 .vector_type,
1849 .elem_type,
1850 .indexable_ptr_len,
1851 .anyframe_type,
1852 .as,
1853 .as_node,
1854 .bit_and,
1855 .bitcast,
1856 .bitcast_result_ptr,
1857 .bit_or,
1858 .block,
1859 .block_inline,
1860 .suspend_block,
1861 .loop,
1862 .bool_br_and,
1863 .bool_br_or,
1864 .bool_not,
1865 .bool_and,
1866 .bool_or,
1867 .call_compile_time,
1868 .call_nosuspend,
1869 .call_async,
1870 .cmp_lt,
1871 .cmp_lte,
1872 .cmp_eq,
1873 .cmp_gte,
1874 .cmp_gt,
1875 .cmp_neq,
1876 .coerce_result_ptr,
1877 .decl_ref,
1878 .decl_val,
1879 .load,
1880 .div,
1881 .elem_ptr,
1882 .elem_val,
1883 .elem_ptr_node,
1884 .elem_val_node,
1885 .field_ptr,
1886 .field_val,
1887 .field_ptr_named,
1888 .field_val_named,
1889 .func,
1890 .func_inferred,
1891 .int,
1892 .int_big,
1893 .float,
1894 .float128,
1895 .int_type,
1896 .is_non_null,
1897 .is_null,
1898 .is_non_null_ptr,
1899 .is_null_ptr,
1900 .is_err,
1901 .is_err_ptr,
1902 .mod_rem,
1903 .mul,
1904 .mulwrap,
1905 .param_type,
1906 .ref,
1907 .shl,
1908 .shr,
1909 .str,
1910 .sub,
1911 .subwrap,
1912 .negate,
1913 .negate_wrap,
1914 .typeof,
1915 .typeof_elem,
1916 .xor,
1917 .optional_type,
1918 .optional_payload_safe,
1919 .optional_payload_unsafe,
1920 .optional_payload_safe_ptr,
1921 .optional_payload_unsafe_ptr,
1922 .err_union_payload_safe,
1923 .err_union_payload_unsafe,
1924 .err_union_payload_safe_ptr,
1925 .err_union_payload_unsafe_ptr,
1926 .err_union_code,
1927 .err_union_code_ptr,
1928 .ptr_type,
1929 .ptr_type_simple,
1930 .enum_literal,
1931 .merge_error_sets,
1932 .error_union_type,
1933 .bit_not,
1934 .error_value,
1935 .error_to_int,
1936 .int_to_error,
1937 .slice_start,
1938 .slice_end,
1939 .slice_sentinel,
1940 .import,
1941 .switch_block,
1942 .switch_block_multi,
1943 .switch_block_else,
1944 .switch_block_else_multi,
1945 .switch_block_under,
1946 .switch_block_under_multi,
1947 .switch_block_ref,
1948 .switch_block_ref_multi,
1949 .switch_block_ref_else,
1950 .switch_block_ref_else_multi,
1951 .switch_block_ref_under,
1952 .switch_block_ref_under_multi,
1953 .switch_capture,
1954 .switch_capture_ref,
1955 .switch_capture_multi,
1956 .switch_capture_multi_ref,
1957 .switch_capture_else,
1958 .switch_capture_else_ref,
1959 .struct_init_empty,
1960 .struct_init,
1961 .struct_init_ref,
1962 .struct_init_anon,
1963 .struct_init_anon_ref,
1964 .array_init,
1965 .array_init_anon,
1966 .array_init_ref,
1967 .array_init_anon_ref,
1968 .union_init_ptr,
1969 .field_type,
1970 .field_type_ref,
1971 .opaque_decl,
1972 .opaque_decl_anon,
1973 .opaque_decl_func,
1974 .error_set_decl,
1975 .error_set_decl_anon,
1976 .error_set_decl_func,
1977 .int_to_enum,
1978 .enum_to_int,
1979 .type_info,
1980 .size_of,
1981 .bit_size_of,
1982 .log2_int_type,
1983 .typeof_log2_int_type,
1984 .ptr_to_int,
1985 .align_of,
1986 .bool_to_int,
1987 .embed_file,
1988 .error_name,
1989 .sqrt,
1990 .sin,
1991 .cos,
1992 .exp,
1993 .exp2,
1994 .log,
1995 .log2,
1996 .log10,
1997 .fabs,
1998 .floor,
1999 .ceil,
2000 .trunc,
2001 .round,
2002 .tag_name,
2003 .reify,
2004 .type_name,
2005 .frame_type,
2006 .frame_size,
2007 .float_to_int,
2008 .int_to_float,
2009 .int_to_ptr,
2010 .float_cast,
2011 .int_cast,
2012 .err_set_cast,
2013 .ptr_cast,
2014 .truncate,
2015 .align_cast,
2016 .has_decl,
2017 .has_field,
2018 .clz,
2019 .ctz,
2020 .pop_count,
2021 .byte_swap,
2022 .bit_reverse,
2023 .div_exact,
2024 .div_floor,
2025 .div_trunc,
2026 .mod,
2027 .rem,
2028 .shl_exact,
2029 .shr_exact,
2030 .bit_offset_of,
2031 .byte_offset_of,
2032 .cmpxchg_strong,
2033 .cmpxchg_weak,
2034 .splat,
2035 .reduce,
2036 .shuffle,
2037 .atomic_load,
2038 .atomic_rmw,
2039 .atomic_store,
2040 .mul_add,
2041 .builtin_call,
2042 .field_ptr_type,
2043 .field_parent_ptr,
2044 .memcpy,
2045 .memset,
2046 .builtin_async_call,
2047 .c_import,
2048 .@"resume",
2049 .@"await",
2050 .await_nosuspend,
2051 .extended,
2052 => break :b false,
2053
2054 // ZIR instructions that are always either `noreturn` or `void`.
2055 .breakpoint,
2056 .fence,
2057 .dbg_stmt,
2058 .ensure_result_used,
2059 .ensure_result_non_error,
2060 .@"export",
2061 .set_eval_branch_quota,
2062 .ensure_err_payload_void,
2063 .@"break",
2064 .break_inline,
2065 .condbr,
2066 .condbr_inline,
2067 .compile_error,
2068 .ret_node,
2069 .ret_coerce,
2070 .@"unreachable",
2071 .store,
2072 .store_node,
2073 .store_to_block_ptr,
2074 .store_to_inferred_ptr,
2075 .resolve_inferred_alloc,
2076 .repeat,
2077 .repeat_inline,
2078 .validate_struct_init_ptr,
2079 .validate_array_init_ptr,
2080 .panic,
2081 .set_align_stack,
2082 .set_cold,
2083 .set_float_mode,
2084 .set_runtime_safety,
2085 => break :b true,
2086 }
2087 } else switch (maybe_unused_result) {
2088 .none => unreachable,
17822089
1783 const result = try gz.addBin(.array_type, len, elem_type);2090 .void_value,
1784 return rvalue(gz, scope, rl, result, node);2091 .unreachable_value,
2092 => true,
2093
2094 else => false,
2095 };
2096 if (!elide_check) {
2097 _ = try gz.addUnNode(.ensure_result_used, maybe_unused_result, statement);
2098 }
1785}2099}
17862100
1787fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !zir.Inst.Ref {2101fn genDefers(
1788 const tree = gz.tree();2102 gz: *GenZir,
2103 outer_scope: *Scope,
2104 inner_scope: *Scope,
2105 err_code: Zir.Inst.Ref,
2106) InnerError!void {
2107 const astgen = gz.astgen;
2108 const tree = astgen.tree;
1789 const node_datas = tree.nodes.items(.data);2109 const node_datas = tree.nodes.items(.data);
1790 const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel);
17912110
1792 // TODO check for [_]T2111 var scope = inner_scope;
1793 const len = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].lhs);2112 while (scope != outer_scope) {
1794 const elem_type = try typeExpr(gz, scope, extra.elem_type);2113 switch (scope.tag) {
1795 const sentinel = try expr(gz, scope, .{ .ty = elem_type }, extra.sentinel);2114 .gen_zir => scope = scope.cast(GenZir).?.parent,
2115 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
2116 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2117 .defer_normal => {
2118 const defer_scope = scope.cast(Scope.Defer).?;
2119 scope = defer_scope.parent;
2120 const expr_node = node_datas[defer_scope.defer_node].rhs;
2121 try unusedResultExpr(gz, defer_scope.parent, expr_node);
2122 },
2123 .defer_error => {
2124 const defer_scope = scope.cast(Scope.Defer).?;
2125 scope = defer_scope.parent;
2126 if (err_code == .none) continue;
2127 const expr_node = node_datas[defer_scope.defer_node].rhs;
2128 try unusedResultExpr(gz, defer_scope.parent, expr_node);
2129 },
2130 .namespace => unreachable,
2131 .top => unreachable,
2132 }
2133 }
2134}
17962135
1797 const result = try gz.addArrayTypeSentinel(len, elem_type, sentinel);2136fn deferStmt(
1798 return rvalue(gz, scope, rl, result, node);2137 gz: *GenZir,
2138 scope: *Scope,
2139 node: ast.Node.Index,
2140 block_arena: *Allocator,
2141 scope_tag: Scope.Tag,
2142) InnerError!*Scope {
2143 const defer_scope = try block_arena.create(Scope.Defer);
2144 defer_scope.* = .{
2145 .base = .{ .tag = scope_tag },
2146 .parent = scope,
2147 .defer_node = node,
2148 };
2149 return &defer_scope.base;
1799}2150}
18002151
1801fn containerDecl(2152fn varDecl(
1802 gz: *GenZir,2153 gz: *GenZir,
1803 scope: *Scope,2154 scope: *Scope,
1804 rl: ResultLoc,
1805 node: ast.Node.Index,2155 node: ast.Node.Index,
1806 container_decl: ast.full.ContainerDecl,2156 block_arena: *Allocator,
1807) InnerError!zir.Inst.Ref {2157 var_decl: ast.full.VarDecl,
2158) InnerError!*Scope {
2159 try emitDbgNode(gz, node);
1808 const astgen = gz.astgen;2160 const astgen = gz.astgen;
1809 const mod = astgen.mod;2161 const gpa = astgen.gpa;
1810 const gpa = mod.gpa;2162 const tree = astgen.tree;
1811 const tree = gz.tree();
1812 const token_tags = tree.tokens.items(.tag);2163 const token_tags = tree.tokens.items(.tag);
1813 const node_tags = tree.nodes.items(.tag);
1814
1815 // We must not create any types until Sema. Here the goal is only to generate
1816 // ZIR for all the field types, alignments, and default value expressions.
1817
1818 const arg_inst: zir.Inst.Ref = if (container_decl.ast.arg != 0)
1819 try comptimeExpr(gz, scope, .none, container_decl.ast.arg)
1820 else
1821 .none;
1822
1823 switch (token_tags[container_decl.ast.main_token]) {
1824 .keyword_struct => {
1825 const tag = if (container_decl.layout_token) |t| switch (token_tags[t]) {
1826 .keyword_packed => zir.Inst.Tag.struct_decl_packed,
1827 .keyword_extern => zir.Inst.Tag.struct_decl_extern,
1828 else => unreachable,
1829 } else zir.Inst.Tag.struct_decl;
1830 if (container_decl.ast.members.len == 0) {
1831 const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{
1832 .fields_len = 0,
1833 });
1834 return rvalue(gz, scope, rl, result, node);
1835 }
1836
1837 assert(arg_inst == .none);
1838 var fields_data = ArrayListUnmanaged(u32){};
1839 defer fields_data.deinit(gpa);
18402164
1841 // field_name and field_type are both mandatory2165 const name_token = var_decl.ast.mut_token + 1;
1842 try fields_data.ensureCapacity(gpa, container_decl.ast.members.len * 2);2166 const ident_name = try astgen.identAsString(name_token);
1843
1844 // We only need this if there are greater than 16 fields.
1845 var bit_bag = ArrayListUnmanaged(u32){};
1846 defer bit_bag.deinit(gpa);
18472167
1848 var cur_bit_bag: u32 = 0;2168 // Local variables shadowing detection, including function parameters.
1849 var field_index: usize = 0;2169 {
1850 for (container_decl.ast.members) |member_node| {2170 var s = scope;
1851 const member = switch (node_tags[member_node]) {2171 while (true) switch (s.tag) {
1852 .container_field_init => tree.containerFieldInit(member_node),2172 .local_val => {
1853 .container_field_align => tree.containerFieldAlign(member_node),2173 const local_val = s.cast(Scope.LocalVal).?;
1854 .container_field => tree.containerField(member_node),2174 if (local_val.name == ident_name) {
1855 else => continue,2175 const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name)));
1856 };2176 defer gpa.free(name);
1857 if (field_index % 16 == 0 and field_index != 0) {2177 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{
1858 try bit_bag.append(gpa, cur_bit_bag);2178 name,
1859 cur_bit_bag = 0;2179 }, &[_]u32{
2180 try astgen.errNoteTok(
2181 local_val.token_src,
2182 "previously declared here",
2183 .{},
2184 ),
2185 });
1860 }2186 }
1861 if (member.comptime_token) |comptime_token| {2187 s = local_val.parent;
1862 return mod.failTok(scope, comptime_token, "TODO implement comptime struct fields", .{});2188 },
2189 .local_ptr => {
2190 const local_ptr = s.cast(Scope.LocalPtr).?;
2191 if (local_ptr.name == ident_name) {
2192 const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name)));
2193 defer gpa.free(name);
2194 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{
2195 name,
2196 }, &[_]u32{
2197 try astgen.errNoteTok(
2198 local_ptr.token_src,
2199 "previously declared here",
2200 .{},
2201 ),
2202 });
1863 }2203 }
1864 try fields_data.ensureCapacity(gpa, fields_data.items.len + 4);2204 s = local_ptr.parent;
18652205 },
1866 const field_name = try gz.identAsString(member.ast.name_token);2206 .namespace => {
1867 fields_data.appendAssumeCapacity(field_name);2207 const ns = s.cast(Scope.Namespace).?;
18682208 const decl_node = ns.decls.get(ident_name) orelse {
1869 const field_type = try typeExpr(gz, scope, member.ast.type_expr);2209 s = ns.parent;
1870 fields_data.appendAssumeCapacity(@enumToInt(field_type));2210 continue;
2211 };
2212 const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name)));
2213 defer gpa.free(name);
2214 return astgen.failTokNotes(name_token, "local shadows declaration of '{s}'", .{
2215 name,
2216 }, &[_]u32{
2217 try astgen.errNoteNode(decl_node, "declared here", .{}),
2218 });
2219 },
2220 .gen_zir => s = s.cast(GenZir).?.parent,
2221 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
2222 .top => break,
2223 };
2224 }
18712225
1872 const have_align = member.ast.align_expr != 0;2226 if (var_decl.ast.init_node == 0) {
1873 const have_value = member.ast.value_expr != 0;2227 return astgen.failNode(node, "variables must be initialized", .{});
1874 cur_bit_bag = (cur_bit_bag >> 2) |2228 }
1875 (@as(u32, @boolToInt(have_align)) << 30) |
1876 (@as(u32, @boolToInt(have_value)) << 31);
18772229
1878 if (have_align) {2230 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0)
1879 const align_inst = try comptimeExpr(gz, scope, .{ .ty = .u32_type }, member.ast.align_expr);2231 try expr(gz, scope, align_rl, var_decl.ast.align_node)
1880 fields_data.appendAssumeCapacity(@enumToInt(align_inst));2232 else
1881 }2233 .none;
1882 if (have_value) {
1883 const default_inst = try comptimeExpr(gz, scope, .{ .ty = field_type }, member.ast.value_expr);
1884 fields_data.appendAssumeCapacity(@enumToInt(default_inst));
1885 }
18862234
1887 field_index += 1;2235 switch (token_tags[var_decl.ast.mut_token]) {
2236 .keyword_const => {
2237 if (var_decl.comptime_token) |comptime_token| {
2238 return astgen.failTok(comptime_token, "'comptime const' is redundant; instead wrap the initialization expression with 'comptime'", .{});
1888 }2239 }
1889 const empty_slot_count = 16 - (field_index % 16);
1890 cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
18912240
1892 const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{2241 // Depending on the type of AST the initialization expression is, we may need an lvalue
1893 .fields_len = @intCast(u32, container_decl.ast.members.len),2242 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as
1894 });2243 // the variable, no memory location needed.
1895 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +2244 if (align_inst == .none and !nodeMayNeedMemoryLocation(tree, var_decl.ast.init_node)) {
1896 bit_bag.items.len + 1 + fields_data.items.len);2245 const result_loc: ResultLoc = if (var_decl.ast.type_node != 0) .{
1897 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.2246 .ty = try typeExpr(gz, scope, var_decl.ast.type_node),
1898 astgen.extra.appendAssumeCapacity(cur_bit_bag);2247 } else .none;
1899 astgen.extra.appendSliceAssumeCapacity(fields_data.items);2248 const init_inst = try expr(gz, scope, result_loc, var_decl.ast.init_node);
1900 return rvalue(gz, scope, rl, result, node);2249 const sub_scope = try block_arena.create(Scope.LocalVal);
1901 },2250 sub_scope.* = .{
1902 .keyword_union => {2251 .parent = scope,
1903 return mod.failTok(scope, container_decl.ast.main_token, "TODO AstGen for union decl", .{});2252 .gen_zir = gz,
1904 },2253 .name = ident_name,
1905 .keyword_enum => {2254 .inst = init_inst,
1906 if (container_decl.layout_token) |t| {2255 .token_src = name_token,
1907 return mod.failTok(scope, t, "enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type", .{});2256 };
2257 return &sub_scope.base;
1908 }2258 }
1909 // Count total fields as well as how many have explicitly provided tag values.
1910 const counts = blk: {
1911 var values: usize = 0;
1912 var total_fields: usize = 0;
1913 var decls: usize = 0;
1914 var nonexhaustive_node: ast.Node.Index = 0;
1915 for (container_decl.ast.members) |member_node| {
1916 const member = switch (node_tags[member_node]) {
1917 .container_field_init => tree.containerFieldInit(member_node),
1918 .container_field_align => tree.containerFieldAlign(member_node),
1919 .container_field => tree.containerField(member_node),
1920 else => {
1921 decls += 1;
1922 continue;
1923 },
1924 };
1925 if (member.comptime_token) |comptime_token| {
1926 return mod.failTok(scope, comptime_token, "enum fields cannot be marked comptime", .{});
1927 }
1928 if (member.ast.type_expr != 0) {
1929 return mod.failNode(scope, member.ast.type_expr, "enum fields do not have types", .{});
1930 }
1931 // Alignment expressions in enums are caught by the parser.
1932 assert(member.ast.align_expr == 0);
19332259
1934 const name_token = member.ast.name_token;2260 // Detect whether the initialization expression actually uses the
1935 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {2261 // result location pointer.
1936 if (nonexhaustive_node != 0) {2262 var init_scope = gz.makeSubBlock(scope);
1937 const msg = msg: {2263 defer init_scope.instructions.deinit(gpa);
1938 const msg = try mod.errMsg(2264
1939 scope,2265 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
1940 gz.nodeSrcLoc(member_node),2266 var opt_type_inst: Zir.Inst.Ref = .none;
1941 "redundant non-exhaustive enum mark",2267 if (var_decl.ast.type_node != 0) {
1942 .{},2268 const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node);
1943 );2269 opt_type_inst = type_inst;
1944 errdefer msg.destroy(gpa);2270 if (align_inst == .none) {
1945 const other_src = gz.nodeSrcLoc(nonexhaustive_node);2271 init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node);
1946 try mod.errNote(scope, other_src, msg, "other mark here", .{});2272 } else {
1947 break :msg msg;2273 init_scope.rl_ptr = try gz.addAllocExtended(.{
1948 };2274 .node = node,
1949 return mod.failWithOwnedErrorMsg(scope, msg);2275 .type_inst = type_inst,
1950 }2276 .align_inst = align_inst,
1951 nonexhaustive_node = member_node;2277 .is_const = true,
1952 if (member.ast.value_expr != 0) {2278 .is_comptime = false,
1953 return mod.failNode(scope, member.ast.value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{});2279 });
1954 }
1955 continue;
1956 }
1957 total_fields += 1;
1958 if (member.ast.value_expr != 0) {
1959 values += 1;
1960 }
1961 }2280 }
1962 break :blk .{2281 init_scope.rl_ty_inst = type_inst;
1963 .total_fields = total_fields,2282 } else {
1964 .values = values,2283 const alloc = if (align_inst == .none)
1965 .decls = decls,2284 try init_scope.addNode(.alloc_inferred, node)
1966 .nonexhaustive_node = nonexhaustive_node,2285 else
1967 };2286 try gz.addAllocExtended(.{
1968 };2287 .node = node,
1969 if (counts.total_fields == 0) {2288 .type_inst = .none,
1970 // One can construct an enum with no tags, and it functions the same as `noreturn`. But2289 .align_inst = align_inst,
1971 // this is only useful for generic code; when explicitly using `enum {}` syntax, there2290 .is_const = true,
1972 // must be at least one tag.2291 .is_comptime = false,
1973 return mod.failNode(scope, node, "enum declarations must have at least one tag", .{});2292 });
2293 resolve_inferred_alloc = alloc;
2294 init_scope.rl_ptr = alloc;
1974 }2295 }
1975 if (counts.nonexhaustive_node != 0 and arg_inst == .none) {2296 const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope };
1976 const msg = msg: {2297 const init_inst = try expr(&init_scope, &init_scope.base, init_result_loc, var_decl.ast.init_node);
1977 const msg = try mod.errMsg(2298 const zir_tags = astgen.instructions.items(.tag);
1978 scope,2299 const zir_datas = astgen.instructions.items(.data);
1979 gz.nodeSrcLoc(node),2300
1980 "non-exhaustive enum missing integer tag type",2301 const parent_zir = &gz.instructions;
1981 .{},2302 if (align_inst == .none and init_scope.rvalue_rl_count == 1) {
1982 );2303 // Result location pointer not used. We don't need an alloc for this
1983 errdefer msg.destroy(gpa);2304 // const local, and type inference becomes trivial.
1984 const other_src = gz.nodeSrcLoc(counts.nonexhaustive_node);2305 // Move the init_scope instructions into the parent scope, eliding
1985 try mod.errNote(scope, other_src, msg, "marked non-exhaustive here", .{});2306 // the alloc instruction and the store_to_block_ptr instruction.
1986 break :msg msg;2307 try parent_zir.ensureUnusedCapacity(gpa, init_scope.instructions.items.len);
2308 for (init_scope.instructions.items) |src_inst| {
2309 if (gz.indexToRef(src_inst) == init_scope.rl_ptr) continue;
2310 if (zir_tags[src_inst] == .store_to_block_ptr) {
2311 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue;
2312 }
2313 parent_zir.appendAssumeCapacity(src_inst);
2314 }
2315
2316 const sub_scope = try block_arena.create(Scope.LocalVal);
2317 sub_scope.* = .{
2318 .parent = scope,
2319 .gen_zir = gz,
2320 .name = ident_name,
2321 .inst = init_inst,
2322 .token_src = name_token,
1987 };2323 };
1988 return mod.failWithOwnedErrorMsg(scope, msg);2324 return &sub_scope.base;
1989 }2325 }
1990 if (counts.values == 0 and counts.decls == 0 and arg_inst == .none) {2326 // The initialization expression took advantage of the result location
1991 // No explicitly provided tag values and no top level declarations! In this case,2327 // of the const local. In this case we will create an alloc and a LocalPtr for it.
1992 // we can construct the enum type in AstGen and it will be correctly shared by all2328 // Move the init_scope instructions into the parent scope, swapping
1993 // generic function instantiations and comptime function calls.2329 // store_to_block_ptr for store_to_inferred_ptr.
1994 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);2330 const expected_len = parent_zir.items.len + init_scope.instructions.items.len;
1995 errdefer new_decl_arena.deinit();2331 try parent_zir.ensureCapacity(gpa, expected_len);
1996 const arena = &new_decl_arena.allocator;2332 for (init_scope.instructions.items) |src_inst| {
19972333 if (zir_tags[src_inst] == .store_to_block_ptr) {
1998 var fields_map: std.StringArrayHashMapUnmanaged(void) = .{};2334 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) {
1999 try fields_map.ensureCapacity(arena, counts.total_fields);2335 zir_tags[src_inst] = .store_to_inferred_ptr;
2000 for (container_decl.ast.members) |member_node| {
2001 if (member_node == counts.nonexhaustive_node)
2002 continue;
2003 const member = switch (node_tags[member_node]) {
2004 .container_field_init => tree.containerFieldInit(member_node),
2005 .container_field_align => tree.containerFieldAlign(member_node),
2006 .container_field => tree.containerField(member_node),
2007 else => unreachable, // We checked earlier.
2008 };
2009 const name_token = member.ast.name_token;
2010 const tag_name = try mod.identifierTokenStringTreeArena(
2011 scope,
2012 name_token,
2013 tree,
2014 arena,
2015 );
2016 const gop = fields_map.getOrPutAssumeCapacity(tag_name);
2017 if (gop.found_existing) {
2018 const msg = msg: {
2019 const msg = try mod.errMsg(
2020 scope,
2021 gz.tokSrcLoc(name_token),
2022 "duplicate enum tag",
2023 .{},
2024 );
2025 errdefer msg.destroy(gpa);
2026 // Iterate to find the other tag. We don't eagerly store it in a hash
2027 // map because in the hot path there will be no compile error and we
2028 // don't need to waste time with a hash map.
2029 const bad_node = for (container_decl.ast.members) |other_member_node| {
2030 const other_member = switch (node_tags[other_member_node]) {
2031 .container_field_init => tree.containerFieldInit(other_member_node),
2032 .container_field_align => tree.containerFieldAlign(other_member_node),
2033 .container_field => tree.containerField(other_member_node),
2034 else => unreachable, // We checked earlier.
2035 };
2036 const other_tag_name = try mod.identifierTokenStringTreeArena(
2037 scope,
2038 other_member.ast.name_token,
2039 tree,
2040 arena,
2041 );
2042 if (mem.eql(u8, tag_name, other_tag_name))
2043 break other_member_node;
2044 } else unreachable;
2045 const other_src = gz.nodeSrcLoc(bad_node);
2046 try mod.errNote(scope, other_src, msg, "other tag here", .{});
2047 break :msg msg;
2048 };
2049 return mod.failWithOwnedErrorMsg(scope, msg);
2050 }2336 }
2051 }2337 }
2052 const enum_simple = try arena.create(Module.EnumSimple);2338 parent_zir.appendAssumeCapacity(src_inst);
2053 enum_simple.* = .{
2054 .owner_decl = astgen.decl,
2055 .node_offset = astgen.decl.nodeIndexToRelative(node),
2056 .fields = fields_map,
2057 };
2058 const enum_ty = try Type.Tag.enum_simple.create(arena, enum_simple);
2059 const enum_val = try Value.Tag.ty.create(arena, enum_ty);
2060 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
2061 .ty = Type.initTag(.type),
2062 .val = enum_val,
2063 });
2064 const decl_index = try mod.declareDeclDependency(astgen.decl, new_decl);
2065 const result = try gz.addDecl(.decl_val, decl_index, node);
2066 return rvalue(gz, scope, rl, result, node);
2067 }2339 }
2068 // In this case we must generate ZIR code for the tag values, similar to2340 assert(parent_zir.items.len == expected_len);
2069 // how structs are handled above. The new anonymous Decl will be created in2341 if (resolve_inferred_alloc != .none) {
2070 // Sema, not AstGen.2342 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
2071 return mod.failNode(scope, node, "TODO AstGen for enum decl with decls or explicitly provided field values", .{});2343 }
2344 const sub_scope = try block_arena.create(Scope.LocalPtr);
2345 sub_scope.* = .{
2346 .parent = scope,
2347 .gen_zir = gz,
2348 .name = ident_name,
2349 .ptr = init_scope.rl_ptr,
2350 .token_src = name_token,
2351 };
2352 return &sub_scope.base;
2072 },2353 },
2073 .keyword_opaque => {2354 .keyword_var => {
2074 const result = try gz.addNode(.opaque_decl, node);2355 const is_comptime = var_decl.comptime_token != null;
2075 return rvalue(gz, scope, rl, result, node);2356 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
2357 const var_data: struct {
2358 result_loc: ResultLoc,
2359 alloc: Zir.Inst.Ref,
2360 } = if (var_decl.ast.type_node != 0) a: {
2361 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);
2362 const alloc = alloc: {
2363 if (align_inst == .none) {
2364 const tag: Zir.Inst.Tag = if (is_comptime) .alloc_comptime else .alloc_mut;
2365 break :alloc try gz.addUnNode(tag, type_inst, node);
2366 } else {
2367 break :alloc try gz.addAllocExtended(.{
2368 .node = node,
2369 .type_inst = type_inst,
2370 .align_inst = align_inst,
2371 .is_const = false,
2372 .is_comptime = is_comptime,
2373 });
2374 }
2375 };
2376 break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } };
2377 } else a: {
2378 const alloc = alloc: {
2379 if (align_inst == .none) {
2380 const tag: Zir.Inst.Tag = if (is_comptime) .alloc_inferred_comptime else .alloc_inferred_mut;
2381 break :alloc try gz.addNode(tag, node);
2382 } else {
2383 break :alloc try gz.addAllocExtended(.{
2384 .node = node,
2385 .type_inst = .none,
2386 .align_inst = align_inst,
2387 .is_const = false,
2388 .is_comptime = is_comptime,
2389 });
2390 }
2391 };
2392 resolve_inferred_alloc = alloc;
2393 break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } };
2394 };
2395 const init_inst = try expr(gz, scope, var_data.result_loc, var_decl.ast.init_node);
2396 if (resolve_inferred_alloc != .none) {
2397 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
2398 }
2399 const sub_scope = try block_arena.create(Scope.LocalPtr);
2400 sub_scope.* = .{
2401 .parent = scope,
2402 .gen_zir = gz,
2403 .name = ident_name,
2404 .ptr = var_data.alloc,
2405 .token_src = name_token,
2406 };
2407 return &sub_scope.base;
2076 },2408 },
2077 else => unreachable,2409 else => unreachable,
2078 }2410 }
2079}2411}
20802412
2081fn errorSetDecl(2413fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void {
2082 gz: *GenZir,2414 // The instruction emitted here is for debugging runtime code.
2083 scope: *Scope,2415 // If the current block will be evaluated only during semantic analysis
2084 rl: ResultLoc,2416 // then no dbg_stmt ZIR instruction is needed.
2085 node: ast.Node.Index,2417 if (gz.force_comptime) return;
2086) InnerError!zir.Inst.Ref {
2087 const astgen = gz.astgen;
2088 const mod = astgen.mod;
2089 const tree = gz.tree();
2090 const main_tokens = tree.nodes.items(.main_token);
2091 const token_tags = tree.tokens.items(.tag);
20922418
2093 // Count how many fields there are.2419 const astgen = gz.astgen;
2094 const error_token = main_tokens[node];2420 const tree = astgen.tree;
2095 const count: usize = count: {2421 const node_tags = tree.nodes.items(.tag);
2096 var tok_i = error_token + 2;2422 const token_starts = tree.tokens.items(.start);
2097 var count: usize = 0;2423 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
2098 while (true) : (tok_i += 1) {2424 const node_start = token_starts[tree.firstToken(node)];
2099 switch (token_tags[tok_i]) {2425 const source = tree.source[decl_start..node_start];
2100 .doc_comment, .comma => {},2426 const loc = std.zig.findLineColumn(source, source.len);
2101 .identifier => count += 1,2427 _ = try gz.add(.{ .tag = .dbg_stmt, .data = .{
2102 .r_brace => break :count count,2428 .dbg_stmt = .{
2103 else => unreachable,2429 .line = @intCast(u32, loc.line),
2104 }2430 .column = @intCast(u32, loc.column),
2105 } else unreachable; // TODO should not need else unreachable here2431 },
2106 };2432 } });
2433}
21072434
2108 const gpa = mod.gpa;2435fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {
2109 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);2436 try emitDbgNode(gz, infix_node);
2110 errdefer new_decl_arena.deinit();2437 const astgen = gz.astgen;
2111 const arena = &new_decl_arena.allocator;2438 const tree = astgen.tree;
2439 const node_datas = tree.nodes.items(.data);
2440 const main_tokens = tree.nodes.items(.main_token);
2441 const node_tags = tree.nodes.items(.tag);
21122442
2113 const fields = try arena.alloc([]const u8, count);2443 const lhs = node_datas[infix_node].lhs;
2114 {2444 const rhs = node_datas[infix_node].rhs;
2115 var tok_i = error_token + 2;2445 if (node_tags[lhs] == .identifier) {
2116 var field_i: usize = 0;2446 // This intentionally does not support `@"_"` syntax.
2117 while (true) : (tok_i += 1) {2447 const ident_name = tree.tokenSlice(main_tokens[lhs]);
2118 switch (token_tags[tok_i]) {2448 if (mem.eql(u8, ident_name, "_")) {
2119 .doc_comment, .comma => {},2449 _ = try expr(gz, scope, .discard, rhs);
2120 .identifier => {2450 return;
2121 fields[field_i] = try mod.identifierTokenStringTreeArena(scope, tok_i, tree, arena);
2122 field_i += 1;
2123 },
2124 .r_brace => break,
2125 else => unreachable,
2126 }
2127 }2451 }
2128 }2452 }
2129 const error_set = try arena.create(Module.ErrorSet);2453 const lvalue = try lvalExpr(gz, scope, lhs);
2130 error_set.* = .{2454 _ = try expr(gz, scope, .{ .ptr = lvalue }, rhs);
2131 .owner_decl = astgen.decl,
2132 .node_offset = astgen.decl.nodeIndexToRelative(node),
2133 .names_ptr = fields.ptr,
2134 .names_len = @intCast(u32, fields.len),
2135 };
2136 const error_set_ty = try Type.Tag.error_set.create(arena, error_set);
2137 const error_set_val = try Value.Tag.ty.create(arena, error_set_ty);
2138 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
2139 .ty = Type.initTag(.type),
2140 .val = error_set_val,
2141 });
2142 const decl_index = try mod.declareDeclDependency(astgen.decl, new_decl);
2143 const result = try gz.addDecl(.decl_val, decl_index, node);
2144 return rvalue(gz, scope, rl, result, node);
2145}2455}
21462456
2147fn orelseCatchExpr(2457fn assignOp(
2148 parent_gz: *GenZir,2458 gz: *GenZir,
2149 scope: *Scope,2459 scope: *Scope,
2150 rl: ResultLoc,2460 infix_node: ast.Node.Index,
2151 node: ast.Node.Index,2461 op_inst_tag: Zir.Inst.Tag,
2152 lhs: ast.Node.Index,2462) InnerError!void {
2153 cond_op: zir.Inst.Tag,2463 try emitDbgNode(gz, infix_node);
2154 unwrap_op: zir.Inst.Tag,2464 const astgen = gz.astgen;
2155 unwrap_code_op: zir.Inst.Tag,2465 const tree = astgen.tree;
2156 rhs: ast.Node.Index,2466 const node_datas = tree.nodes.items(.data);
2157 payload_token: ?ast.TokenIndex,
2158) InnerError!zir.Inst.Ref {
2159 const mod = parent_gz.astgen.mod;
2160 const tree = parent_gz.tree();
21612467
2162 var block_scope: GenZir = .{2468 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
2163 .parent = scope,2469 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
2164 .astgen = parent_gz.astgen,2470 const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node);
2165 .force_comptime = parent_gz.force_comptime,2471 const rhs = try expr(gz, scope, .{ .ty = lhs_type }, node_datas[infix_node].rhs);
2166 .instructions = .{},
2167 };
2168 block_scope.setBreakResultLoc(rl);
2169 defer block_scope.instructions.deinit(mod.gpa);
21702472
2171 // This could be a pointer or value depending on the `operand_rl` parameter.2473 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{
2172 // We cannot use `block_scope.break_result_loc` because that has the bare2474 .lhs = lhs,
2173 // type, whereas this expression has the optional type. Later we make2475 .rhs = rhs,
2174 // up for this fact by calling rvalue on the else branch.2476 });
2175 block_scope.break_count += 1;2477 _ = try gz.addBin(.store, lhs_ptr, result);
2478}
21762479
2177 // TODO handle catch2480fn assignShift(
2178 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {
2179 .ref => .ref,
2180 .discard, .none, .none_or_ref, .block_ptr, .inferred_ptr => .none,
2181 .ty => |elem_ty| blk: {
2182 const wrapped_ty = try block_scope.addUnNode(.optional_type, elem_ty, node);
2183 break :blk .{ .ty = wrapped_ty };
2184 },
2185 .ptr => |ptr_ty| blk: {
2186 const wrapped_ty = try block_scope.addUnNode(.optional_type_from_ptr_elem, ptr_ty, node);
2187 break :blk .{ .ty = wrapped_ty };
2188 },
2189 };
2190 const operand = try expr(&block_scope, &block_scope.base, operand_rl, lhs);
2191 const cond = try block_scope.addUnNode(cond_op, operand, node);
2192 const condbr = try block_scope.addCondBr(.condbr, node);
2193
2194 const block = try parent_gz.addBlock(.block, node);
2195 try parent_gz.instructions.append(mod.gpa, block);
2196 try block_scope.setBlockBody(block);
2197
2198 var then_scope: GenZir = .{
2199 .parent = scope,
2200 .astgen = parent_gz.astgen,
2201 .force_comptime = block_scope.force_comptime,
2202 .instructions = .{},
2203 };
2204 defer then_scope.instructions.deinit(mod.gpa);
2205
2206 var err_val_scope: Scope.LocalVal = undefined;
2207 const then_sub_scope = blk: {
2208 const payload = payload_token orelse break :blk &then_scope.base;
2209 if (mem.eql(u8, tree.tokenSlice(payload), "_")) {
2210 return mod.failTok(&then_scope.base, payload, "discard of error capture; omit it instead", .{});
2211 }
2212 const err_name = try mod.identifierTokenString(scope, payload);
2213 err_val_scope = .{
2214 .parent = &then_scope.base,
2215 .gen_zir = &then_scope,
2216 .name = err_name,
2217 .inst = try then_scope.addUnNode(unwrap_code_op, operand, node),
2218 .src = parent_gz.tokSrcLoc(payload),
2219 };
2220 break :blk &err_val_scope.base;
2221 };
2222
2223 block_scope.break_count += 1;
2224 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, rhs);
2225 // We hold off on the break instructions as well as copying the then/else
2226 // instructions into place until we know whether to keep store_to_block_ptr
2227 // instructions or not.
2228
2229 var else_scope: GenZir = .{
2230 .parent = scope,
2231 .astgen = parent_gz.astgen,
2232 .force_comptime = block_scope.force_comptime,
2233 .instructions = .{},
2234 };
2235 defer else_scope.instructions.deinit(mod.gpa);
2236
2237 // This could be a pointer or value depending on `unwrap_op`.
2238 const unwrapped_payload = try else_scope.addUnNode(unwrap_op, operand, node);
2239 const else_result = switch (rl) {
2240 .ref => unwrapped_payload,
2241 else => try rvalue(&else_scope, &else_scope.base, block_scope.break_result_loc, unwrapped_payload, node),
2242 };
2243
2244 return finishThenElseBlock(
2245 parent_gz,
2246 scope,
2247 rl,
2248 node,
2249 &block_scope,
2250 &then_scope,
2251 &else_scope,
2252 condbr,
2253 cond,
2254 node,
2255 node,
2256 then_result,
2257 else_result,
2258 block,
2259 block,
2260 .@"break",
2261 );
2262}
2263
2264fn finishThenElseBlock(
2265 parent_gz: *GenZir,
2266 parent_scope: *Scope,
2267 rl: ResultLoc,
2268 node: ast.Node.Index,
2269 block_scope: *GenZir,
2270 then_scope: *GenZir,
2271 else_scope: *GenZir,
2272 condbr: zir.Inst.Index,
2273 cond: zir.Inst.Ref,
2274 then_src: ast.Node.Index,
2275 else_src: ast.Node.Index,
2276 then_result: zir.Inst.Ref,
2277 else_result: zir.Inst.Ref,
2278 main_block: zir.Inst.Index,
2279 then_break_block: zir.Inst.Index,
2280 break_tag: zir.Inst.Tag,
2281) InnerError!zir.Inst.Ref {
2282 // We now have enough information to decide whether the result instruction should
2283 // be communicated via result location pointer or break instructions.
2284 const strat = rl.strategy(block_scope);
2285 const astgen = block_scope.astgen;
2286 switch (strat.tag) {
2287 .break_void => {
2288 if (!astgen.refIsNoReturn(then_result)) {
2289 _ = try then_scope.addBreak(break_tag, then_break_block, .void_value);
2290 }
2291 const elide_else = if (else_result != .none) astgen.refIsNoReturn(else_result) else false;
2292 if (!elide_else) {
2293 _ = try else_scope.addBreak(break_tag, main_block, .void_value);
2294 }
2295 assert(!strat.elide_store_to_block_ptr_instructions);
2296 try setCondBrPayload(condbr, cond, then_scope, else_scope);
2297 return astgen.indexToRef(main_block);
2298 },
2299 .break_operand => {
2300 if (!astgen.refIsNoReturn(then_result)) {
2301 _ = try then_scope.addBreak(break_tag, then_break_block, then_result);
2302 }
2303 if (else_result != .none) {
2304 if (!astgen.refIsNoReturn(else_result)) {
2305 _ = try else_scope.addBreak(break_tag, main_block, else_result);
2306 }
2307 } else {
2308 _ = try else_scope.addBreak(break_tag, main_block, .void_value);
2309 }
2310 if (strat.elide_store_to_block_ptr_instructions) {
2311 try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope);
2312 } else {
2313 try setCondBrPayload(condbr, cond, then_scope, else_scope);
2314 }
2315 const block_ref = astgen.indexToRef(main_block);
2316 switch (rl) {
2317 .ref => return block_ref,
2318 else => return rvalue(parent_gz, parent_scope, rl, block_ref, node),
2319 }
2320 },
2321 }
2322}
2323
2324/// Return whether the identifier names of two tokens are equal. Resolves @""
2325/// tokens without allocating.
2326/// OK in theory it could do it without allocating. This implementation
2327/// allocates when the @"" form is used.
2328fn tokenIdentEql(mod: *Module, scope: *Scope, token1: ast.TokenIndex, token2: ast.TokenIndex) !bool {
2329 const ident_name_1 = try mod.identifierTokenString(scope, token1);
2330 const ident_name_2 = try mod.identifierTokenString(scope, token2);
2331 return mem.eql(u8, ident_name_1, ident_name_2);
2332}
2333
2334pub fn fieldAccess(
2335 gz: *GenZir,2481 gz: *GenZir,
2336 scope: *Scope,2482 scope: *Scope,
2337 rl: ResultLoc,2483 infix_node: ast.Node.Index,
2338 node: ast.Node.Index,2484 op_inst_tag: Zir.Inst.Tag,
2339) InnerError!zir.Inst.Ref {2485) InnerError!void {
2486 try emitDbgNode(gz, infix_node);
2340 const astgen = gz.astgen;2487 const astgen = gz.astgen;
2341 const mod = astgen.mod;2488 const tree = astgen.tree;
2342 const tree = gz.tree();
2343 const main_tokens = tree.nodes.items(.main_token);
2344 const node_datas = tree.nodes.items(.data);2489 const node_datas = tree.nodes.items(.data);
23452490
2346 const object_node = node_datas[node].lhs;2491 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
2347 const dot_token = main_tokens[node];2492 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
2348 const field_ident = dot_token + 1;2493 const rhs_type = try gz.addUnNode(.typeof_log2_int_type, lhs, infix_node);
2349 const str_index = try gz.identAsString(field_ident);2494 const rhs = try expr(gz, scope, .{ .ty = rhs_type }, node_datas[infix_node].rhs);
2350 switch (rl) {2495
2351 .ref => return gz.addPlNode(.field_ptr, node, zir.Inst.Field{2496 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{
2352 .lhs = try expr(gz, scope, .ref, object_node),2497 .lhs = lhs,
2353 .field_name_start = str_index,2498 .rhs = rhs,
2354 }),2499 });
2355 else => return rvalue(gz, scope, rl, try gz.addPlNode(.field_val, node, zir.Inst.Field{2500 _ = try gz.addBin(.store, lhs_ptr, result);
2356 .lhs = try expr(gz, scope, .none_or_ref, object_node),
2357 .field_name_start = str_index,
2358 }), node),
2359 }
2360}2501}
23612502
2362fn arrayAccess(2503fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
2363 gz: *GenZir,2504 const astgen = gz.astgen;
2364 scope: *Scope,2505 const tree = astgen.tree;
2365 rl: ResultLoc,
2366 node: ast.Node.Index,
2367) InnerError!zir.Inst.Ref {
2368 const tree = gz.tree();
2369 const main_tokens = tree.nodes.items(.main_token);
2370 const node_datas = tree.nodes.items(.data);2506 const node_datas = tree.nodes.items(.data);
2371 switch (rl) {2507
2372 .ref => return gz.addBin(2508 const operand = try expr(gz, scope, bool_rl, node_datas[node].lhs);
2373 .elem_ptr,2509 const result = try gz.addUnNode(.bool_not, operand, node);
2374 try expr(gz, scope, .ref, node_datas[node].lhs),2510 return rvalue(gz, scope, rl, result, node);
2375 try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),
2376 ),
2377 else => return rvalue(gz, scope, rl, try gz.addBin(
2378 .elem_val,
2379 try expr(gz, scope, .none_or_ref, node_datas[node].lhs),
2380 try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),
2381 ), node),
2382 }
2383}2511}
23842512
2385fn simpleBinOp(2513fn bitNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
2386 gz: *GenZir,2514 const astgen = gz.astgen;
2387 scope: *Scope,2515 const tree = astgen.tree;
2388 rl: ResultLoc,
2389 node: ast.Node.Index,
2390 op_inst_tag: zir.Inst.Tag,
2391) InnerError!zir.Inst.Ref {
2392 const tree = gz.tree();
2393 const node_datas = tree.nodes.items(.data);2516 const node_datas = tree.nodes.items(.data);
23942517
2395 const result = try gz.addPlNode(op_inst_tag, node, zir.Inst.Bin{2518 const operand = try expr(gz, scope, .none, node_datas[node].lhs);
2396 .lhs = try expr(gz, scope, .none, node_datas[node].lhs),2519 const result = try gz.addUnNode(.bit_not, operand, node);
2397 .rhs = try expr(gz, scope, .none, node_datas[node].rhs),
2398 });
2399 return rvalue(gz, scope, rl, result, node);2520 return rvalue(gz, scope, rl, result, node);
2400}2521}
24012522
2402fn simpleStrTok(2523fn negation(
2403 gz: *GenZir,2524 gz: *GenZir,
2404 scope: *Scope,2525 scope: *Scope,
2405 rl: ResultLoc,2526 rl: ResultLoc,
2406 ident_token: ast.TokenIndex,
2407 node: ast.Node.Index,2527 node: ast.Node.Index,
2408 op_inst_tag: zir.Inst.Tag,2528 tag: Zir.Inst.Tag,
2409) InnerError!zir.Inst.Ref {2529) InnerError!Zir.Inst.Ref {
2410 const str_index = try gz.identAsString(ident_token);2530 const astgen = gz.astgen;
2411 const result = try gz.addStrTok(op_inst_tag, str_index, ident_token);2531 const tree = astgen.tree;
2532 const node_datas = tree.nodes.items(.data);
2533
2534 const operand = try expr(gz, scope, .none, node_datas[node].lhs);
2535 const result = try gz.addUnNode(tag, operand, node);
2412 return rvalue(gz, scope, rl, result, node);2536 return rvalue(gz, scope, rl, result, node);
2413}2537}
24142538
2415fn boolBinOp(2539fn ptrType(
2416 gz: *GenZir,2540 gz: *GenZir,
2417 scope: *Scope,2541 scope: *Scope,
2418 rl: ResultLoc,2542 rl: ResultLoc,
2419 node: ast.Node.Index,2543 node: ast.Node.Index,
2420 zir_tag: zir.Inst.Tag,2544 ptr_info: ast.full.PtrType,
2421) InnerError!zir.Inst.Ref {2545) InnerError!Zir.Inst.Ref {
2422 const node_datas = gz.tree().nodes.items(.data);2546 const astgen = gz.astgen;
24232547 const tree = astgen.tree;
2424 const lhs = try expr(gz, scope, .{ .ty = .bool_type }, node_datas[node].lhs);
2425 const bool_br = try gz.addBoolBr(zir_tag, lhs);
2426
2427 var rhs_scope: GenZir = .{
2428 .parent = scope,
2429 .astgen = gz.astgen,
2430 .force_comptime = gz.force_comptime,
2431 };
2432 defer rhs_scope.instructions.deinit(gz.astgen.mod.gpa);
2433 const rhs = try expr(&rhs_scope, &rhs_scope.base, .{ .ty = .bool_type }, node_datas[node].rhs);
2434 _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs);
2435 try rhs_scope.setBoolBrBody(bool_br);
2436
2437 const block_ref = gz.astgen.indexToRef(bool_br);
2438 return rvalue(gz, scope, rl, block_ref, node);
2439}
24402548
2441fn ifExpr(2549 const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type);
2442 parent_gz: *GenZir,
2443 scope: *Scope,
2444 rl: ResultLoc,
2445 node: ast.Node.Index,
2446 if_full: ast.full.If,
2447) InnerError!zir.Inst.Ref {
2448 const mod = parent_gz.astgen.mod;
24492550
2450 var block_scope: GenZir = .{2551 const simple = ptr_info.ast.align_node == 0 and
2451 .parent = scope,2552 ptr_info.ast.sentinel == 0 and
2452 .astgen = parent_gz.astgen,2553 ptr_info.ast.bit_range_start == 0;
2453 .force_comptime = parent_gz.force_comptime,
2454 .instructions = .{},
2455 };
2456 block_scope.setBreakResultLoc(rl);
2457 defer block_scope.instructions.deinit(mod.gpa);
24582554
2459 const cond = c: {2555 if (simple) {
2460 // TODO https://github.com/ziglang/zig/issues/79292556 const result = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
2461 if (if_full.error_token) |error_token| {2557 .ptr_type_simple = .{
2462 return mod.failTok(scope, error_token, "TODO implement if error union", .{});2558 .is_allowzero = ptr_info.allowzero_token != null,
2463 } else if (if_full.payload_token) |payload_token| {2559 .is_mutable = ptr_info.const_token == null,
2464 return mod.failTok(scope, payload_token, "TODO implement if optional", .{});2560 .is_volatile = ptr_info.volatile_token != null,
2465 } else {2561 .size = ptr_info.size,
2466 break :c try expr(&block_scope, &block_scope.base, .{ .ty = .bool_type }, if_full.ast.cond_expr);2562 .elem_type = elem_type,
2467 }2563 },
2468 };2564 } });
2565 return rvalue(gz, scope, rl, result, node);
2566 }
24692567
2470 const condbr = try block_scope.addCondBr(.condbr, node);2568 var sentinel_ref: Zir.Inst.Ref = .none;
2569 var align_ref: Zir.Inst.Ref = .none;
2570 var bit_start_ref: Zir.Inst.Ref = .none;
2571 var bit_end_ref: Zir.Inst.Ref = .none;
2572 var trailing_count: u32 = 0;
24712573
2472 const block = try parent_gz.addBlock(.block, node);2574 if (ptr_info.ast.sentinel != 0) {
2473 try parent_gz.instructions.append(mod.gpa, block);2575 sentinel_ref = try expr(gz, scope, .{ .ty = elem_type }, ptr_info.ast.sentinel);
2474 try block_scope.setBlockBody(block);2576 trailing_count += 1;
2577 }
2578 if (ptr_info.ast.align_node != 0) {
2579 align_ref = try expr(gz, scope, align_rl, ptr_info.ast.align_node);
2580 trailing_count += 1;
2581 }
2582 if (ptr_info.ast.bit_range_start != 0) {
2583 assert(ptr_info.ast.bit_range_end != 0);
2584 bit_start_ref = try expr(gz, scope, .none, ptr_info.ast.bit_range_start);
2585 bit_end_ref = try expr(gz, scope, .none, ptr_info.ast.bit_range_end);
2586 trailing_count += 2;
2587 }
24752588
2476 var then_scope: GenZir = .{2589 const gpa = gz.astgen.gpa;
2477 .parent = scope,2590 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
2478 .astgen = parent_gz.astgen,2591 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
2479 .force_comptime = block_scope.force_comptime,2592 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
2480 .instructions = .{},2593 @typeInfo(Zir.Inst.PtrType).Struct.fields.len + trailing_count);
2481 };
2482 defer then_scope.instructions.deinit(mod.gpa);
24832594
2484 // declare payload to the then_scope2595 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.PtrType{ .elem_type = elem_type });
2485 const then_sub_scope = &then_scope.base;2596 if (sentinel_ref != .none) {
2597 gz.astgen.extra.appendAssumeCapacity(@enumToInt(sentinel_ref));
2598 }
2599 if (align_ref != .none) {
2600 gz.astgen.extra.appendAssumeCapacity(@enumToInt(align_ref));
2601 }
2602 if (bit_start_ref != .none) {
2603 gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_start_ref));
2604 gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_end_ref));
2605 }
24862606
2487 block_scope.break_count += 1;2607 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
2488 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, if_full.ast.then_expr);2608 const result = gz.indexToRef(new_index);
2489 // We hold off on the break instructions as well as copying the then/else2609 gz.astgen.instructions.appendAssumeCapacity(.{ .tag = .ptr_type, .data = .{
2490 // instructions into place until we know whether to keep store_to_block_ptr2610 .ptr_type = .{
2491 // instructions or not.2611 .flags = .{
24922612 .is_allowzero = ptr_info.allowzero_token != null,
2493 var else_scope: GenZir = .{2613 .is_mutable = ptr_info.const_token == null,
2494 .parent = scope,2614 .is_volatile = ptr_info.volatile_token != null,
2495 .astgen = parent_gz.astgen,2615 .has_sentinel = sentinel_ref != .none,
2496 .force_comptime = block_scope.force_comptime,2616 .has_align = align_ref != .none,
2497 .instructions = .{},2617 .has_bit_range = bit_start_ref != .none,
2498 };2618 },
2499 defer else_scope.instructions.deinit(mod.gpa);2619 .size = ptr_info.size,
25002620 .payload_index = payload_index,
2501 const else_node = if_full.ast.else_expr;2621 },
2502 const else_info: struct {2622 } });
2503 src: ast.Node.Index,2623 gz.instructions.appendAssumeCapacity(new_index);
2504 result: zir.Inst.Ref,
2505 } = if (else_node != 0) blk: {
2506 block_scope.break_count += 1;
2507 const sub_scope = &else_scope.base;
2508 break :blk .{
2509 .src = else_node,
2510 .result = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node),
2511 };
2512 } else .{
2513 .src = if_full.ast.then_expr,
2514 .result = .none,
2515 };
25162624
2517 return finishThenElseBlock(2625 return rvalue(gz, scope, rl, result, node);
2518 parent_gz,
2519 scope,
2520 rl,
2521 node,
2522 &block_scope,
2523 &then_scope,
2524 &else_scope,
2525 condbr,
2526 cond,
2527 if_full.ast.then_expr,
2528 else_info.src,
2529 then_result,
2530 else_info.result,
2531 block,
2532 block,
2533 .@"break",
2534 );
2535}2626}
25362627
2537fn setCondBrPayload(2628fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {
2538 condbr: zir.Inst.Index,2629 const astgen = gz.astgen;
2539 cond: zir.Inst.Ref,2630 const tree = astgen.tree;
2540 then_scope: *GenZir,2631 const node_datas = tree.nodes.items(.data);
2541 else_scope: *GenZir,2632 const node_tags = tree.nodes.items(.tag);
2542) !void {2633 const main_tokens = tree.nodes.items(.main_token);
2543 const astgen = then_scope.astgen;
25442634
2545 try astgen.extra.ensureCapacity(astgen.mod.gpa, astgen.extra.items.len +2635 const len_node = node_datas[node].lhs;
2546 @typeInfo(zir.Inst.CondBr).Struct.fields.len +2636 if (node_tags[len_node] == .identifier and
2547 then_scope.instructions.items.len + else_scope.instructions.items.len);2637 mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_"))
2638 {
2639 return astgen.failNode(len_node, "unable to infer array size", .{});
2640 }
2641 const len = try expr(gz, scope, .{ .ty = .usize_type }, len_node);
2642 const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);
25482643
2549 const zir_datas = astgen.instructions.items(.data);2644 const result = try gz.addBin(.array_type, len, elem_type);
2550 zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(zir.Inst.CondBr{2645 return rvalue(gz, scope, rl, result, node);
2551 .condition = cond,
2552 .then_body_len = @intCast(u32, then_scope.instructions.items.len),
2553 .else_body_len = @intCast(u32, else_scope.instructions.items.len),
2554 });
2555 astgen.extra.appendSliceAssumeCapacity(then_scope.instructions.items);
2556 astgen.extra.appendSliceAssumeCapacity(else_scope.instructions.items);
2557}2646}
25582647
2559/// If `elide_block_store_ptr` is set, expects to find exactly 1 .store_to_block_ptr instruction.2648fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {
2560fn setCondBrPayloadElideBlockStorePtr(2649 const astgen = gz.astgen;
2561 condbr: zir.Inst.Index,2650 const tree = astgen.tree;
2562 cond: zir.Inst.Ref,2651 const node_datas = tree.nodes.items(.data);
2563 then_scope: *GenZir,2652 const node_tags = tree.nodes.items(.tag);
2564 else_scope: *GenZir,2653 const main_tokens = tree.nodes.items(.main_token);
2565) !void {2654 const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel);
2566 const astgen = then_scope.astgen;
25672655
2568 try astgen.extra.ensureCapacity(astgen.mod.gpa, astgen.extra.items.len +2656 const len_node = node_datas[node].lhs;
2569 @typeInfo(zir.Inst.CondBr).Struct.fields.len +2657 if (node_tags[len_node] == .identifier and
2570 then_scope.instructions.items.len + else_scope.instructions.items.len - 2);2658 mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_"))
2659 {
2660 return astgen.failNode(len_node, "unable to infer array size", .{});
2661 }
2662 const len = try expr(gz, scope, .{ .ty = .usize_type }, len_node);
2663 const elem_type = try typeExpr(gz, scope, extra.elem_type);
2664 const sentinel = try expr(gz, scope, .{ .ty = elem_type }, extra.sentinel);
25712665
2572 const zir_datas = astgen.instructions.items(.data);2666 const result = try gz.addArrayTypeSentinel(len, elem_type, sentinel);
2573 zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(zir.Inst.CondBr{2667 return rvalue(gz, scope, rl, result, node);
2574 .condition = cond,2668}
2575 .then_body_len = @intCast(u32, then_scope.instructions.items.len - 1),
2576 .else_body_len = @intCast(u32, else_scope.instructions.items.len - 1),
2577 });
25782669
2579 const zir_tags = astgen.instructions.items(.tag);2670const WipDecls = struct {
2580 for ([_]*GenZir{ then_scope, else_scope }) |scope| {2671 decl_index: usize = 0,
2581 for (scope.instructions.items) |src_inst| {2672 cur_bit_bag: u32 = 0,
2582 if (zir_tags[src_inst] != .store_to_block_ptr) {2673 bit_bag: ArrayListUnmanaged(u32) = .{},
2583 astgen.extra.appendAssumeCapacity(src_inst);2674 payload: ArrayListUnmanaged(u32) = .{},
2584 }2675
2676 const bits_per_field = 4;
2677 const fields_per_u32 = 32 / bits_per_field;
2678
2679 fn next(
2680 wip_decls: *WipDecls,
2681 gpa: *Allocator,
2682 is_pub: bool,
2683 is_export: bool,
2684 has_align: bool,
2685 has_section: bool,
2686 ) Allocator.Error!void {
2687 if (wip_decls.decl_index % fields_per_u32 == 0 and wip_decls.decl_index != 0) {
2688 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
2689 wip_decls.cur_bit_bag = 0;
2585 }2690 }
2691 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> bits_per_field) |
2692 (@as(u32, @boolToInt(is_pub)) << 28) |
2693 (@as(u32, @boolToInt(is_export)) << 29) |
2694 (@as(u32, @boolToInt(has_align)) << 30) |
2695 (@as(u32, @boolToInt(has_section)) << 31);
2696 wip_decls.decl_index += 1;
2586 }2697 }
2587}
25882698
2589fn whileExpr(2699 fn deinit(wip_decls: *WipDecls, gpa: *Allocator) void {
2590 parent_gz: *GenZir,2700 wip_decls.bit_bag.deinit(gpa);
2591 scope: *Scope,2701 wip_decls.payload.deinit(gpa);
2592 rl: ResultLoc,
2593 node: ast.Node.Index,
2594 while_full: ast.full.While,
2595) InnerError!zir.Inst.Ref {
2596 const mod = parent_gz.astgen.mod;
2597 if (while_full.label_token) |label_token| {
2598 try checkLabelRedefinition(mod, scope, label_token);
2599 }2702 }
2703};
26002704
2601 const is_inline = parent_gz.force_comptime or while_full.inline_token != null;2705fn fnDecl(
2602 const loop_tag: zir.Inst.Tag = if (is_inline) .block_inline else .loop;2706 astgen: *AstGen,
2603 const loop_block = try parent_gz.addBlock(loop_tag, node);2707 gz: *GenZir,
2604 try parent_gz.instructions.append(mod.gpa, loop_block);2708 scope: *Scope,
2709 wip_decls: *WipDecls,
2710 decl_node: ast.Node.Index,
2711 body_node: ast.Node.Index,
2712 fn_proto: ast.full.FnProto,
2713) InnerError!void {
2714 const gpa = astgen.gpa;
2715 const tree = astgen.tree;
2716 const token_tags = tree.tokens.items(.tag);
2717
2718 const fn_name_token = fn_proto.name_token orelse {
2719 return astgen.failTok(fn_proto.ast.fn_token, "missing function name", .{});
2720 };
2721 const fn_name_str_index = try astgen.identAsString(fn_name_token);
26052722
2606 var loop_scope: GenZir = .{2723 try astgen.declareNewName(scope, fn_name_str_index, decl_node);
2724
2725 // We insert this at the beginning so that its instruction index marks the
2726 // start of the top level declaration.
2727 const block_inst = try gz.addBlock(.block_inline, fn_proto.ast.proto_node);
2728
2729 var decl_gz: GenZir = .{
2730 .force_comptime = true,
2731 .decl_node_index = fn_proto.ast.proto_node,
2732 .decl_line = gz.calcLine(decl_node),
2607 .parent = scope,2733 .parent = scope,
2608 .astgen = parent_gz.astgen,2734 .astgen = astgen,
2609 .force_comptime = parent_gz.force_comptime,
2610 .instructions = .{},
2611 };2735 };
2612 loop_scope.setBreakResultLoc(rl);2736 defer decl_gz.instructions.deinit(gpa);
2613 defer loop_scope.instructions.deinit(mod.gpa);
26142737
2615 var continue_scope: GenZir = .{2738 const is_pub = fn_proto.visib_token != null;
2616 .parent = &loop_scope.base,2739 const is_export = blk: {
2617 .astgen = parent_gz.astgen,2740 const maybe_export_token = fn_proto.extern_export_token orelse break :blk false;
2618 .force_comptime = loop_scope.force_comptime,2741 break :blk token_tags[maybe_export_token] == .keyword_export;
2619 .instructions = .{},2742 };
2743 const is_extern = blk: {
2744 const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false;
2745 break :blk token_tags[maybe_extern_token] == .keyword_extern;
2746 };
2747 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
2748 break :inst try expr(&decl_gz, &decl_gz.base, align_rl, fn_proto.ast.align_expr);
2749 };
2750 const section_inst: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {
2751 break :inst try comptimeExpr(&decl_gz, &decl_gz.base, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr);
2620 };2752 };
2621 defer continue_scope.instructions.deinit(mod.gpa);
26222753
2623 const cond = c: {2754 try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, section_inst != .none);
2624 // TODO https://github.com/ziglang/zig/issues/79292755
2625 if (while_full.error_token) |error_token| {2756 // The AST params array does not contain anytype and ... parameters.
2626 return mod.failTok(scope, error_token, "TODO implement while error union", .{});2757 // We must iterate to count how many param types to allocate.
2627 } else if (while_full.payload_token) |payload_token| {2758 const param_count = blk: {
2628 return mod.failTok(scope, payload_token, "TODO implement while optional", .{});2759 var count: usize = 0;
2629 } else {2760 var it = fn_proto.iterate(tree.*);
2630 const bool_type_rl: ResultLoc = .{ .ty = .bool_type };2761 while (it.next()) |param| {
2631 break :c try expr(&continue_scope, &continue_scope.base, bool_type_rl, while_full.ast.cond_expr);2762 if (param.anytype_ellipsis3) |token| switch (token_tags[token]) {
2763 .ellipsis3 => break,
2764 .keyword_anytype => {},
2765 else => unreachable,
2766 };
2767 count += 1;
2632 }2768 }
2769 break :blk count;
2633 };2770 };
2771 const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);
2772 defer gpa.free(param_types);
26342773
2635 const condbr_tag: zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;2774 var is_var_args = false;
2636 const condbr = try continue_scope.addCondBr(condbr_tag, node);2775 {
2637 const block_tag: zir.Inst.Tag = if (is_inline) .block_inline else .block;2776 var param_type_i: usize = 0;
2638 const cond_block = try loop_scope.addBlock(block_tag, node);2777 var it = fn_proto.iterate(tree.*);
2639 try loop_scope.instructions.append(mod.gpa, cond_block);2778 while (it.next()) |param| : (param_type_i += 1) {
2640 try continue_scope.setBlockBody(cond_block);2779 if (param.anytype_ellipsis3) |token| {
26412780 switch (token_tags[token]) {
2642 // TODO avoid emitting the continue expr when there2781 .keyword_anytype => {
2643 // are no jumps to it. This happens when the last statement of a while body is noreturn2782 param_types[param_type_i] = .none;
2644 // and there are no `continue` statements.2783 continue;
2645 if (while_full.ast.cont_expr != 0) {2784 },
2646 _ = try expr(&loop_scope, &loop_scope.base, .{ .ty = .void_type }, while_full.ast.cont_expr);2785 .ellipsis3 => {
2786 is_var_args = true;
2787 break;
2788 },
2789 else => unreachable,
2790 }
2791 }
2792 const param_type_node = param.type_expr;
2793 assert(param_type_node != 0);
2794 param_types[param_type_i] =
2795 try expr(&decl_gz, &decl_gz.base, .{ .ty = .type_type }, param_type_node);
2796 }
2797 assert(param_type_i == param_count);
2647 }2798 }
2648 const repeat_tag: zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
2649 _ = try loop_scope.addNode(repeat_tag, node);
26502799
2651 try loop_scope.setBlockBody(loop_block);2800 const lib_name: u32 = if (fn_proto.lib_name) |lib_name_token| blk: {
2652 loop_scope.break_block = loop_block;2801 const lib_name_str = try astgen.strLitAsString(lib_name_token);
2653 loop_scope.continue_block = cond_block;2802 break :blk lib_name_str.index;
2654 if (while_full.label_token) |label_token| {2803 } else 0;
2655 loop_scope.label = @as(?GenZir.Label, GenZir.Label{2804
2656 .token = label_token,2805 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
2657 .block_inst = loop_block,2806 const is_inferred_error = token_tags[maybe_bang] == .bang;
2807
2808 const return_type_inst = try AstGen.expr(
2809 &decl_gz,
2810 &decl_gz.base,
2811 .{ .ty = .type_type },
2812 fn_proto.ast.return_type,
2813 );
2814
2815 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
2816 try AstGen.expr(
2817 &decl_gz,
2818 &decl_gz.base,
2819 .{ .ty = .calling_convention_type },
2820 fn_proto.ast.callconv_expr,
2821 )
2822 else if (is_extern) // note: https://github.com/ziglang/zig/issues/5269
2823 Zir.Inst.Ref.calling_convention_c
2824 else
2825 Zir.Inst.Ref.none;
2826
2827 const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {
2828 if (!is_extern) {
2829 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{});
2830 }
2831 if (is_inferred_error) {
2832 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
2833 }
2834 break :func try decl_gz.addFunc(.{
2835 .src_node = decl_node,
2836 .ret_ty = return_type_inst,
2837 .param_types = param_types,
2838 .body = &[0]Zir.Inst.Index{},
2839 .cc = cc,
2840 .align_inst = .none, // passed in the per-decl data
2841 .lib_name = lib_name,
2842 .is_var_args = is_var_args,
2843 .is_inferred_error = false,
2844 .is_test = false,
2845 .is_extern = true,
2658 });2846 });
2659 }2847 } else func: {
2848 if (is_var_args) {
2849 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{});
2850 }
26602851
2661 var then_scope: GenZir = .{2852 var fn_gz: GenZir = .{
2662 .parent = &continue_scope.base,2853 .force_comptime = false,
2663 .astgen = parent_gz.astgen,2854 .decl_node_index = fn_proto.ast.proto_node,
2664 .force_comptime = continue_scope.force_comptime,2855 .decl_line = decl_gz.decl_line,
2665 .instructions = .{},2856 .parent = &decl_gz.base,
2666 };2857 .astgen = astgen,
2667 defer then_scope.instructions.deinit(mod.gpa);2858 };
2859 defer fn_gz.instructions.deinit(gpa);
26682860
2669 const then_sub_scope = &then_scope.base;2861 const prev_fn_block = astgen.fn_block;
2862 astgen.fn_block = &fn_gz;
26702863
2671 loop_scope.break_count += 1;2864 // Iterate over the parameters. We put the param names as the first N
2672 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr);2865 // items inside `extra` so that debug info later can refer to the parameter names
2866 // even while the respective source code is unloaded.
2867 try astgen.extra.ensureUnusedCapacity(gpa, param_count);
26732868
2674 var else_scope: GenZir = .{2869 {
2675 .parent = &continue_scope.base,2870 var params_scope = &fn_gz.base;
2676 .astgen = parent_gz.astgen,2871 var i: usize = 0;
2677 .force_comptime = continue_scope.force_comptime,2872 var it = fn_proto.iterate(tree.*);
2678 .instructions = .{},2873 while (it.next()) |param| : (i += 1) {
2679 };2874 const name_token = param.name_token orelse {
2680 defer else_scope.instructions.deinit(mod.gpa);2875 return astgen.failNode(param.type_expr, "missing parameter name", .{});
2876 };
2877 const param_name = try astgen.identAsString(name_token);
2878 // Create an arg instruction. This is needed to emit a semantic analysis
2879 // error for shadowing decls.
2880 // TODO emit a compile error here for shadowing locals.
2881 const arg_inst = try fn_gz.addStrTok(.arg, param_name, name_token);
2882 const sub_scope = try astgen.arena.create(Scope.LocalVal);
2883 sub_scope.* = .{
2884 .parent = params_scope,
2885 .gen_zir = &fn_gz,
2886 .name = param_name,
2887 .inst = arg_inst,
2888 .token_src = name_token,
2889 };
2890 params_scope = &sub_scope.base;
26812891
2682 const else_node = while_full.ast.else_expr;2892 // Additionally put the param name into `string_bytes` and reference it with
2683 const else_info: struct {2893 // `extra` so that we have access to the data in codegen, for debug info.
2684 src: ast.Node.Index,2894 const str_index = try astgen.identAsString(name_token);
2685 result: zir.Inst.Ref,2895 astgen.extra.appendAssumeCapacity(str_index);
2686 } = if (else_node != 0) blk: {2896 }
2687 loop_scope.break_count += 1;2897
2688 const sub_scope = &else_scope.base;2898 _ = try expr(&fn_gz, params_scope, .none, body_node);
2689 break :blk .{2899 }
2690 .src = else_node,2900
2691 .result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node),2901 const need_implicit_ret = blk: {
2902 if (fn_gz.instructions.items.len == 0)
2903 break :blk true;
2904 const last = fn_gz.instructions.items[fn_gz.instructions.items.len - 1];
2905 const zir_tags = astgen.instructions.items(.tag);
2906 break :blk !zir_tags[last].isNoReturn();
2692 };2907 };
2693 } else .{2908 if (need_implicit_ret) {
2694 .src = while_full.ast.then_expr,2909 // Since we are adding the return instruction here, we must handle the coercion.
2695 .result = .none,2910 // We do this by using the `ret_coerce` instruction.
2911 _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
2912 }
2913
2914 astgen.fn_block = prev_fn_block;
2915
2916 break :func try decl_gz.addFunc(.{
2917 .src_node = decl_node,
2918 .ret_ty = return_type_inst,
2919 .param_types = param_types,
2920 .body = fn_gz.instructions.items,
2921 .cc = cc,
2922 .align_inst = .none, // passed in the per-decl data
2923 .lib_name = lib_name,
2924 .is_var_args = is_var_args,
2925 .is_inferred_error = is_inferred_error,
2926 .is_test = false,
2927 .is_extern = false,
2928 });
2696 };2929 };
26972930
2698 if (loop_scope.label) |some| {2931 // We add this at the end so that its instruction index marks the end range
2699 if (!some.used) {2932 // of the top level declaration.
2700 return mod.failTok(scope, some.token, "unused while loop label", .{});2933 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);
2701 }2934 try decl_gz.setBlockBody(block_inst);
2935
2936 try wip_decls.payload.ensureUnusedCapacity(gpa, 9);
2937 {
2938 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
2939 const casted = @bitCast([4]u32, contents_hash);
2940 wip_decls.payload.appendSliceAssumeCapacity(&casted);
2941 }
2942 {
2943 const line_delta = decl_gz.decl_line - gz.decl_line;
2944 wip_decls.payload.appendAssumeCapacity(line_delta);
2945 }
2946 wip_decls.payload.appendAssumeCapacity(fn_name_str_index);
2947 wip_decls.payload.appendAssumeCapacity(block_inst);
2948 if (align_inst != .none) {
2949 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));
2950 }
2951 if (section_inst != .none) {
2952 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));
2702 }2953 }
2703 const break_tag: zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
2704 return finishThenElseBlock(
2705 parent_gz,
2706 scope,
2707 rl,
2708 node,
2709 &loop_scope,
2710 &then_scope,
2711 &else_scope,
2712 condbr,
2713 cond,
2714 while_full.ast.then_expr,
2715 else_info.src,
2716 then_result,
2717 else_info.result,
2718 loop_block,
2719 cond_block,
2720 break_tag,
2721 );
2722}2954}
27232955
2724fn forExpr(2956fn globalVarDecl(
2725 parent_gz: *GenZir,2957 astgen: *AstGen,
2958 gz: *GenZir,
2726 scope: *Scope,2959 scope: *Scope,
2727 rl: ResultLoc,2960 wip_decls: *WipDecls,
2728 node: ast.Node.Index,2961 node: ast.Node.Index,
2729 for_full: ast.full.While,2962 var_decl: ast.full.VarDecl,
2730) InnerError!zir.Inst.Ref {2963) InnerError!void {
2731 const mod = parent_gz.astgen.mod;2964 const gpa = astgen.gpa;
2732 if (for_full.label_token) |label_token| {2965 const tree = astgen.tree;
2733 try checkLabelRedefinition(mod, scope, label_token);
2734 }
2735 // Set up variables and constants.
2736 const is_inline = parent_gz.force_comptime or for_full.inline_token != null;
2737 const tree = parent_gz.tree();
2738 const token_tags = tree.tokens.items(.tag);2966 const token_tags = tree.tokens.items(.tag);
27392967
2740 const array_ptr = try expr(parent_gz, scope, .ref, for_full.ast.cond_expr);2968 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
2741 const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr);2969 // We do this at the beginning so that the instruction index marks the range start
2970 // of the top level declaration.
2971 const block_inst = try gz.addBlock(.block_inline, node);
27422972
2743 const index_ptr = blk: {2973 const name_token = var_decl.ast.mut_token + 1;
2744 const index_ptr = try parent_gz.addUnNode(.alloc, .usize_type, node);2974 const name_str_index = try astgen.identAsString(name_token);
2745 // initialize to zero
2746 _ = try parent_gz.addBin(.store, index_ptr, .zero_usize);
2747 break :blk index_ptr;
2748 };
27492975
2750 const loop_tag: zir.Inst.Tag = if (is_inline) .block_inline else .loop;2976 try astgen.declareNewName(scope, name_str_index, node);
2751 const loop_block = try parent_gz.addBlock(loop_tag, node);
2752 try parent_gz.instructions.append(mod.gpa, loop_block);
27532977
2754 var loop_scope: GenZir = .{2978 var block_scope: GenZir = .{
2755 .parent = scope,2979 .parent = scope,
2756 .astgen = parent_gz.astgen,2980 .decl_node_index = node,
2757 .force_comptime = parent_gz.force_comptime,2981 .decl_line = gz.calcLine(node),
2758 .instructions = .{},2982 .astgen = astgen,
2983 .force_comptime = true,
2984 .anon_name_strategy = .parent,
2759 };2985 };
2760 loop_scope.setBreakResultLoc(rl);2986 defer block_scope.instructions.deinit(gpa);
2761 defer loop_scope.instructions.deinit(mod.gpa);
27622987
2763 var cond_scope: GenZir = .{2988 const is_pub = var_decl.visib_token != null;
2764 .parent = &loop_scope.base,2989 const is_export = blk: {
2765 .astgen = parent_gz.astgen,2990 const maybe_export_token = var_decl.extern_export_token orelse break :blk false;
2766 .force_comptime = loop_scope.force_comptime,2991 break :blk token_tags[maybe_export_token] == .keyword_export;
2767 .instructions = .{},2992 };
2993 const is_extern = blk: {
2994 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;
2995 break :blk token_tags[maybe_extern_token] == .keyword_extern;
2768 };2996 };
2769 defer cond_scope.instructions.deinit(mod.gpa);2997 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: {
2998 break :inst try expr(&block_scope, &block_scope.base, align_rl, var_decl.ast.align_node);
2999 };
3000 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {
3001 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node);
3002 };
3003 try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, section_inst != .none);
27703004
2771 // check condition i < array_expr.len3005 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
2772 const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);3006 if (!is_mutable) {
2773 const cond = try cond_scope.addPlNode(.cmp_lt, for_full.ast.cond_expr, zir.Inst.Bin{3007 return astgen.failTok(tok, "threadlocal variable cannot be constant", .{});
2774 .lhs = index,3008 }
2775 .rhs = len,3009 break :blk true;
2776 });3010 } else false;
3011
3012 const lib_name: u32 = if (var_decl.lib_name) |lib_name_token| blk: {
3013 const lib_name_str = try astgen.strLitAsString(lib_name_token);
3014 break :blk lib_name_str.index;
3015 } else 0;
3016
3017 assert(var_decl.comptime_token == null); // handled by parser
3018
3019 const var_inst: Zir.Inst.Ref = if (var_decl.ast.init_node != 0) vi: {
3020 if (is_extern) {
3021 return astgen.failNode(
3022 var_decl.ast.init_node,
3023 "extern variables have no initializers",
3024 .{},
3025 );
3026 }
27773027
2778 const condbr_tag: zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;3028 const type_inst: Zir.Inst.Ref = if (var_decl.ast.type_node != 0)
2779 const condbr = try cond_scope.addCondBr(condbr_tag, node);3029 try expr(
2780 const block_tag: zir.Inst.Tag = if (is_inline) .block_inline else .block;3030 &block_scope,
2781 const cond_block = try loop_scope.addBlock(block_tag, node);3031 &block_scope.base,
2782 try loop_scope.instructions.append(mod.gpa, cond_block);3032 .{ .ty = .type_type },
2783 try cond_scope.setBlockBody(cond_block);3033 var_decl.ast.type_node,
27843034 )
2785 // Increment the index variable.3035 else
2786 const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);3036 .none;
2787 const index_plus_one = try loop_scope.addPlNode(.add, node, zir.Inst.Bin{3037
2788 .lhs = index_2,3038 const init_inst = try expr(
2789 .rhs = .one_usize,3039 &block_scope,
2790 });3040 &block_scope.base,
2791 _ = try loop_scope.addBin(.store, index_ptr, index_plus_one);3041 if (type_inst != .none) .{ .ty = type_inst } else .none,
2792 const repeat_tag: zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;3042 var_decl.ast.init_node,
2793 _ = try loop_scope.addNode(repeat_tag, node);3043 );
27943044
2795 try loop_scope.setBlockBody(loop_block);3045 if (is_mutable) {
2796 loop_scope.break_block = loop_block;3046 const var_inst = try block_scope.addVar(.{
2797 loop_scope.continue_block = cond_block;3047 .var_type = type_inst,
2798 if (for_full.label_token) |label_token| {3048 .lib_name = 0,
2799 loop_scope.label = @as(?GenZir.Label, GenZir.Label{3049 .align_inst = .none, // passed via the decls data
2800 .token = label_token,3050 .init = init_inst,
2801 .block_inst = loop_block,3051 .is_extern = false,
3052 .is_threadlocal = is_threadlocal,
3053 });
3054 break :vi var_inst;
3055 } else {
3056 break :vi init_inst;
3057 }
3058 } else if (!is_extern) {
3059 return astgen.failNode(node, "variables must be initialized", .{});
3060 } else if (var_decl.ast.type_node != 0) vi: {
3061 // Extern variable which has an explicit type.
3062 const type_inst = try typeExpr(&block_scope, &block_scope.base, var_decl.ast.type_node);
3063
3064 const var_inst = try block_scope.addVar(.{
3065 .var_type = type_inst,
3066 .lib_name = lib_name,
3067 .align_inst = .none, // passed via the decls data
3068 .init = .none,
3069 .is_extern = true,
3070 .is_threadlocal = is_threadlocal,
2802 });3071 });
2803 }3072 break :vi var_inst;
28043073 } else {
2805 var then_scope: GenZir = .{3074 return astgen.failNode(node, "unable to infer variable type", .{});
2806 .parent = &cond_scope.base,
2807 .astgen = parent_gz.astgen,
2808 .force_comptime = cond_scope.force_comptime,
2809 .instructions = .{},
2810 };3075 };
2811 defer then_scope.instructions.deinit(mod.gpa);3076 // We do this at the end so that the instruction index marks the end
3077 // range of a top level declaration.
3078 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);
3079 try block_scope.setBlockBody(block_inst);
28123080
2813 var index_scope: Scope.LocalPtr = undefined;3081 try wip_decls.payload.ensureUnusedCapacity(gpa, 9);
2814 const then_sub_scope = blk: {3082 {
2815 const payload_token = for_full.payload_token.?;3083 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
2816 const ident = if (token_tags[payload_token] == .asterisk)3084 const casted = @bitCast([4]u32, contents_hash);
2817 payload_token + 13085 wip_decls.payload.appendSliceAssumeCapacity(&casted);
2818 else3086 }
2819 payload_token;3087 {
2820 const is_ptr = ident != payload_token;3088 const line_delta = block_scope.decl_line - gz.decl_line;
2821 const value_name = tree.tokenSlice(ident);3089 wip_decls.payload.appendAssumeCapacity(line_delta);
2822 if (!mem.eql(u8, value_name, "_")) {3090 }
2823 return mod.failNode(&then_scope.base, ident, "TODO implement for loop value payload", .{});3091 wip_decls.payload.appendAssumeCapacity(name_str_index);
2824 } else if (is_ptr) {3092 wip_decls.payload.appendAssumeCapacity(block_inst);
2825 return mod.failTok(&then_scope.base, payload_token, "pointer modifier invalid on discard", .{});3093 if (align_inst != .none) {
2826 }3094 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));
3095 }
3096 if (section_inst != .none) {
3097 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));
3098 }
3099}
28273100
2828 const index_token = if (token_tags[ident + 1] == .comma)3101fn comptimeDecl(
2829 ident + 23102 astgen: *AstGen,
2830 else3103 gz: *GenZir,
2831 break :blk &then_scope.base;3104 scope: *Scope,
2832 if (mem.eql(u8, tree.tokenSlice(index_token), "_")) {3105 wip_decls: *WipDecls,
2833 return mod.failTok(&then_scope.base, index_token, "discard of index capture; omit it instead", .{});3106 node: ast.Node.Index,
2834 }3107) InnerError!void {
2835 const index_name = try mod.identifierTokenString(&then_scope.base, index_token);3108 const gpa = astgen.gpa;
2836 index_scope = .{3109 const tree = astgen.tree;
2837 .parent = &then_scope.base,3110 const node_datas = tree.nodes.items(.data);
2838 .gen_zir = &then_scope,3111 const body_node = node_datas[node].lhs;
2839 .name = index_name,
2840 .ptr = index_ptr,
2841 .src = parent_gz.tokSrcLoc(index_token),
2842 };
2843 break :blk &index_scope.base;
2844 };
28453112
2846 loop_scope.break_count += 1;3113 // Up top so the ZIR instruction index marks the start range of this
2847 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr);3114 // top-level declaration.
3115 const block_inst = try gz.addBlock(.block_inline, node);
3116 try wip_decls.next(gpa, false, false, false, false);
28483117
2849 var else_scope: GenZir = .{3118 var decl_block: GenZir = .{
2850 .parent = &cond_scope.base,3119 .force_comptime = true,
2851 .astgen = parent_gz.astgen,3120 .decl_node_index = node,
2852 .force_comptime = cond_scope.force_comptime,3121 .decl_line = gz.calcLine(node),
2853 .instructions = .{},3122 .parent = scope,
3123 .astgen = astgen,
2854 };3124 };
2855 defer else_scope.instructions.deinit(mod.gpa);3125 defer decl_block.instructions.deinit(gpa);
28563126
2857 const else_node = for_full.ast.else_expr;3127 const block_result = try expr(&decl_block, &decl_block.base, .none, body_node);
2858 const else_info: struct {3128 if (decl_block.instructions.items.len == 0 or !decl_block.refIsNoReturn(block_result)) {
2859 src: ast.Node.Index,3129 _ = try decl_block.addBreak(.break_inline, block_inst, .void_value);
2860 result: zir.Inst.Ref,3130 }
2861 } = if (else_node != 0) blk: {3131 try decl_block.setBlockBody(block_inst);
2862 loop_scope.break_count += 1;
2863 const sub_scope = &else_scope.base;
2864 break :blk .{
2865 .src = else_node,
2866 .result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node),
2867 };
2868 } else .{
2869 .src = for_full.ast.then_expr,
2870 .result = .none,
2871 };
28723132
2873 if (loop_scope.label) |some| {3133 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
2874 if (!some.used) {3134 {
2875 return mod.failTok(scope, some.token, "unused for loop label", .{});3135 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
2876 }3136 const casted = @bitCast([4]u32, contents_hash);
3137 wip_decls.payload.appendSliceAssumeCapacity(&casted);
2877 }3138 }
2878 const break_tag: zir.Inst.Tag = if (is_inline) .break_inline else .@"break";3139 {
2879 return finishThenElseBlock(3140 const line_delta = decl_block.decl_line - gz.decl_line;
2880 parent_gz,3141 wip_decls.payload.appendAssumeCapacity(line_delta);
2881 scope,3142 }
2882 rl,3143 wip_decls.payload.appendAssumeCapacity(0);
2883 node,3144 wip_decls.payload.appendAssumeCapacity(block_inst);
2884 &loop_scope,
2885 &then_scope,
2886 &else_scope,
2887 condbr,
2888 cond,
2889 for_full.ast.then_expr,
2890 else_info.src,
2891 then_result,
2892 else_info.result,
2893 loop_block,
2894 cond_block,
2895 break_tag,
2896 );
2897}3145}
28983146
2899fn getRangeNode(3147fn usingnamespaceDecl(
2900 node_tags: []const ast.Node.Tag,3148 astgen: *AstGen,
2901 node_datas: []const ast.Node.Data,3149 gz: *GenZir,
3150 scope: *Scope,
3151 wip_decls: *WipDecls,
2902 node: ast.Node.Index,3152 node: ast.Node.Index,
2903) ?ast.Node.Index {3153) InnerError!void {
2904 switch (node_tags[node]) {3154 const gpa = astgen.gpa;
2905 .switch_range => return node,3155 const tree = astgen.tree;
2906 .grouped_expression => unreachable,3156 const node_datas = tree.nodes.items(.data);
2907 else => return null,3157
3158 const type_expr = node_datas[node].lhs;
3159 const is_pub = blk: {
3160 const main_tokens = tree.nodes.items(.main_token);
3161 const token_tags = tree.tokens.items(.tag);
3162 const main_token = main_tokens[node];
3163 break :blk (main_token > 0 and token_tags[main_token - 1] == .keyword_pub);
3164 };
3165 // Up top so the ZIR instruction index marks the start range of this
3166 // top-level declaration.
3167 const block_inst = try gz.addBlock(.block_inline, node);
3168 try wip_decls.next(gpa, is_pub, true, false, false);
3169
3170 var decl_block: GenZir = .{
3171 .force_comptime = true,
3172 .decl_node_index = node,
3173 .decl_line = gz.calcLine(node),
3174 .parent = scope,
3175 .astgen = astgen,
3176 };
3177 defer decl_block.instructions.deinit(gpa);
3178
3179 const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr);
3180 _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst);
3181 try decl_block.setBlockBody(block_inst);
3182
3183 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
3184 {
3185 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3186 const casted = @bitCast([4]u32, contents_hash);
3187 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3188 }
3189 {
3190 const line_delta = decl_block.decl_line - gz.decl_line;
3191 wip_decls.payload.appendAssumeCapacity(line_delta);
2908 }3192 }
3193 wip_decls.payload.appendAssumeCapacity(0);
3194 wip_decls.payload.appendAssumeCapacity(block_inst);
2909}3195}
29103196
2911pub const SwitchProngSrc = union(enum) {3197fn testDecl(
2912 scalar: u32,3198 astgen: *AstGen,
2913 multi: Multi,3199 gz: *GenZir,
2914 range: Multi,3200 scope: *Scope,
3201 wip_decls: *WipDecls,
3202 node: ast.Node.Index,
3203) InnerError!void {
3204 const gpa = astgen.gpa;
3205 const tree = astgen.tree;
3206 const node_datas = tree.nodes.items(.data);
3207 const body_node = node_datas[node].rhs;
3208
3209 // Up top so the ZIR instruction index marks the start range of this
3210 // top-level declaration.
3211 const block_inst = try gz.addBlock(.block_inline, node);
3212
3213 try wip_decls.next(gpa, false, false, false, false);
29153214
2916 pub const Multi = struct {3215 var decl_block: GenZir = .{
2917 prong: u32,3216 .force_comptime = true,
2918 item: u32,3217 .decl_node_index = node,
3218 .decl_line = gz.calcLine(node),
3219 .parent = scope,
3220 .astgen = astgen,
2919 };3221 };
3222 defer decl_block.instructions.deinit(gpa);
29203223
2921 pub const RangeExpand = enum { none, first, last };3224 const test_name: u32 = blk: {
2922
2923 /// This function is intended to be called only when it is certain that we need
2924 /// the LazySrcLoc in order to emit a compile error.
2925 pub fn resolve(
2926 prong_src: SwitchProngSrc,
2927 decl: *Decl,
2928 switch_node_offset: i32,
2929 range_expand: RangeExpand,
2930 ) LazySrcLoc {
2931 @setCold(true);
2932 const switch_node = decl.relativeToNodeIndex(switch_node_offset);
2933 const tree = decl.container.file_scope.base.tree();
2934 const main_tokens = tree.nodes.items(.main_token);3225 const main_tokens = tree.nodes.items(.main_token);
2935 const node_datas = tree.nodes.items(.data);3226 const token_tags = tree.tokens.items(.tag);
2936 const node_tags = tree.nodes.items(.tag);3227 const test_token = main_tokens[node];
2937 const extra = tree.extraData(node_datas[switch_node].rhs, ast.Node.SubRange);3228 const str_lit_token = test_token + 1;
2938 const case_nodes = tree.extra_data[extra.start..extra.end];3229 if (token_tags[str_lit_token] == .string_literal) {
29393230 break :blk try astgen.testNameString(str_lit_token);
2940 var multi_i: u32 = 0;3231 }
2941 var scalar_i: u32 = 0;3232 // String table index 1 has a special meaning here of test decl with no name.
2942 for (case_nodes) |case_node| {3233 break :blk 1;
2943 const case = switch (node_tags[case_node]) {3234 };
2944 .switch_case_one => tree.switchCaseOne(case_node),
2945 .switch_case => tree.switchCase(case_node),
2946 else => unreachable,
2947 };
2948 if (case.ast.values.len == 0)
2949 continue;
2950 if (case.ast.values.len == 1 and
2951 node_tags[case.ast.values[0]] == .identifier and
2952 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
2953 {
2954 continue;
2955 }
2956 const is_multi = case.ast.values.len != 1 or
2957 getRangeNode(node_tags, node_datas, case.ast.values[0]) != null;
29583235
2959 switch (prong_src) {3236 var fn_block: GenZir = .{
2960 .scalar => |i| if (!is_multi and i == scalar_i) return LazySrcLoc{3237 .force_comptime = false,
2961 .node_offset = decl.nodeIndexToRelative(case.ast.values[0]),3238 .decl_node_index = node,
2962 },3239 .decl_line = decl_block.decl_line,
2963 .multi => |s| if (is_multi and s.prong == multi_i) {3240 .parent = &decl_block.base,
2964 var item_i: u32 = 0;3241 .astgen = astgen,
2965 for (case.ast.values) |item_node| {3242 };
2966 if (getRangeNode(node_tags, node_datas, item_node) != null)3243 defer fn_block.instructions.deinit(gpa);
2967 continue;
29683244
2969 if (item_i == s.item) return LazySrcLoc{3245 const prev_fn_block = astgen.fn_block;
2970 .node_offset = decl.nodeIndexToRelative(item_node),3246 astgen.fn_block = &fn_block;
2971 };3247
2972 item_i += 1;3248 const block_result = try expr(&fn_block, &fn_block.base, .none, body_node);
2973 } else unreachable;3249 if (fn_block.instructions.items.len == 0 or !fn_block.refIsNoReturn(block_result)) {
2974 },3250 // Since we are adding the return instruction here, we must handle the coercion.
2975 .range => |s| if (is_multi and s.prong == multi_i) {3251 // We do this by using the `ret_coerce` instruction.
2976 var range_i: u32 = 0;3252 _ = try fn_block.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
2977 for (case.ast.values) |item_node| {
2978 const range = getRangeNode(node_tags, node_datas, item_node) orelse continue;
2979
2980 if (range_i == s.item) switch (range_expand) {
2981 .none => return LazySrcLoc{
2982 .node_offset = decl.nodeIndexToRelative(item_node),
2983 },
2984 .first => return LazySrcLoc{
2985 .node_offset = decl.nodeIndexToRelative(node_datas[range].lhs),
2986 },
2987 .last => return LazySrcLoc{
2988 .node_offset = decl.nodeIndexToRelative(node_datas[range].rhs),
2989 },
2990 };
2991 range_i += 1;
2992 } else unreachable;
2993 },
2994 }
2995 if (is_multi) {
2996 multi_i += 1;
2997 } else {
2998 scalar_i += 1;
2999 }
3000 } else unreachable;
3001 }3253 }
3002};
30033254
3004fn switchExpr(3255 astgen.fn_block = prev_fn_block;
3005 parent_gz: *GenZir,3256
3006 scope: *Scope,3257 const func_inst = try decl_block.addFunc(.{
3007 rl: ResultLoc,3258 .src_node = node,
3008 switch_node: ast.Node.Index,3259 .ret_ty = .void_type,
3009) InnerError!zir.Inst.Ref {3260 .param_types = &[0]Zir.Inst.Ref{},
3010 const astgen = parent_gz.astgen;3261 .body = fn_block.instructions.items,
3011 const mod = astgen.mod;3262 .cc = .none,
3012 const gpa = mod.gpa;3263 .align_inst = .none,
3013 const tree = parent_gz.tree();3264 .lib_name = 0,
3014 const node_datas = tree.nodes.items(.data);3265 .is_var_args = false,
3015 const node_tags = tree.nodes.items(.tag);3266 .is_inferred_error = true,
3016 const main_tokens = tree.nodes.items(.main_token);3267 .is_test = true,
3017 const token_tags = tree.tokens.items(.tag);3268 .is_extern = false,
3018 const operand_node = node_datas[switch_node].lhs;3269 });
3019 const extra = tree.extraData(node_datas[switch_node].rhs, ast.Node.SubRange);
3020 const case_nodes = tree.extra_data[extra.start..extra.end];
30213270
3022 // We perform two passes over the AST. This first pass is to collect information3271 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);
3023 // for the following variables, make note of the special prong AST node index,3272 try decl_block.setBlockBody(block_inst);
3024 // and bail out with a compile error if there are multiple special prongs present.
3025 var any_payload_is_ref = false;
3026 var scalar_cases_len: u32 = 0;
3027 var multi_cases_len: u32 = 0;
3028 var special_prong: zir.SpecialProng = .none;
3029 var special_node: ast.Node.Index = 0;
3030 var else_src: ?LazySrcLoc = null;
3031 var underscore_src: ?LazySrcLoc = null;
3032 for (case_nodes) |case_node| {
3033 const case = switch (node_tags[case_node]) {
3034 .switch_case_one => tree.switchCaseOne(case_node),
3035 .switch_case => tree.switchCase(case_node),
3036 else => unreachable,
3037 };
3038 if (case.payload_token) |payload_token| {
3039 if (token_tags[payload_token] == .asterisk) {
3040 any_payload_is_ref = true;
3041 }
3042 }
3043 // Check for else/`_` prong.
3044 if (case.ast.values.len == 0) {
3045 const case_src = parent_gz.tokSrcLoc(case.ast.arrow_token - 1);
3046 if (else_src) |src| {
3047 const msg = msg: {
3048 const msg = try mod.errMsg(
3049 scope,
3050 case_src,
3051 "multiple else prongs in switch expression",
3052 .{},
3053 );
3054 errdefer msg.destroy(gpa);
3055 try mod.errNote(scope, src, msg, "previous else prong is here", .{});
3056 break :msg msg;
3057 };
3058 return mod.failWithOwnedErrorMsg(scope, msg);
3059 } else if (underscore_src) |some_underscore| {
3060 const msg = msg: {
3061 const msg = try mod.errMsg(
3062 scope,
3063 parent_gz.nodeSrcLoc(switch_node),
3064 "else and '_' prong in switch expression",
3065 .{},
3066 );
3067 errdefer msg.destroy(gpa);
3068 try mod.errNote(scope, case_src, msg, "else prong is here", .{});
3069 try mod.errNote(scope, some_underscore, msg, "'_' prong is here", .{});
3070 break :msg msg;
3071 };
3072 return mod.failWithOwnedErrorMsg(scope, msg);
3073 }
3074 special_node = case_node;
3075 special_prong = .@"else";
3076 else_src = case_src;
3077 continue;
3078 } else if (case.ast.values.len == 1 and
3079 node_tags[case.ast.values[0]] == .identifier and
3080 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
3081 {
3082 const case_src = parent_gz.tokSrcLoc(case.ast.arrow_token - 1);
3083 if (underscore_src) |src| {
3084 const msg = msg: {
3085 const msg = try mod.errMsg(
3086 scope,
3087 case_src,
3088 "multiple '_' prongs in switch expression",
3089 .{},
3090 );
3091 errdefer msg.destroy(gpa);
3092 try mod.errNote(scope, src, msg, "previous '_' prong is here", .{});
3093 break :msg msg;
3094 };
3095 return mod.failWithOwnedErrorMsg(scope, msg);
3096 } else if (else_src) |some_else| {
3097 const msg = msg: {
3098 const msg = try mod.errMsg(
3099 scope,
3100 parent_gz.nodeSrcLoc(switch_node),
3101 "else and '_' prong in switch expression",
3102 .{},
3103 );
3104 errdefer msg.destroy(gpa);
3105 try mod.errNote(scope, some_else, msg, "else prong is here", .{});
3106 try mod.errNote(scope, case_src, msg, "'_' prong is here", .{});
3107 break :msg msg;
3108 };
3109 return mod.failWithOwnedErrorMsg(scope, msg);
3110 }
3111 special_node = case_node;
3112 special_prong = .under;
3113 underscore_src = case_src;
3114 continue;
3115 }
31163273
3117 if (case.ast.values.len == 1 and3274 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
3118 getRangeNode(node_tags, node_datas, case.ast.values[0]) == null)3275 {
3119 {3276 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3120 scalar_cases_len += 1;3277 const casted = @bitCast([4]u32, contents_hash);
3121 } else {3278 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3122 multi_cases_len += 1;
3123 }
3124 }3279 }
3280 {
3281 const line_delta = decl_block.decl_line - gz.decl_line;
3282 wip_decls.payload.appendAssumeCapacity(line_delta);
3283 }
3284 wip_decls.payload.appendAssumeCapacity(test_name);
3285 wip_decls.payload.appendAssumeCapacity(block_inst);
3286}
31253287
3126 const operand_rl: ResultLoc = if (any_payload_is_ref) .ref else .none;3288fn structDeclInner(
3127 const operand = try expr(parent_gz, scope, operand_rl, operand_node);3289 gz: *GenZir,
3128 // We need the type of the operand to use as the result location for all the prong items.3290 scope: *Scope,
3129 const typeof_tag: zir.Inst.Tag = if (any_payload_is_ref) .typeof_elem else .typeof;3291 node: ast.Node.Index,
3130 const operand_ty_inst = try parent_gz.addUnNode(typeof_tag, operand, operand_node);3292 container_decl: ast.full.ContainerDecl,
3131 const item_rl: ResultLoc = .{ .ty = operand_ty_inst };3293 layout: std.builtin.TypeInfo.ContainerLayout,
3294) InnerError!Zir.Inst.Ref {
3295 if (container_decl.ast.members.len == 0) {
3296 const decl_inst = try gz.reserveInstructionIndex();
3297 try gz.setStruct(decl_inst, .{
3298 .src_node = node,
3299 .layout = layout,
3300 .fields_len = 0,
3301 .body_len = 0,
3302 .decls_len = 0,
3303 });
3304 return gz.indexToRef(decl_inst);
3305 }
31323306
3133 // Contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti.3307 const astgen = gz.astgen;
3134 // This is the header as well as the optional else prong body, as well as all the3308 const gpa = astgen.gpa;
3135 // scalar cases.3309 const tree = astgen.tree;
3136 // At the end we will memcpy this into place.3310 const node_tags = tree.nodes.items(.tag);
3137 var scalar_cases_payload = ArrayListUnmanaged(u32){};3311 const node_datas = tree.nodes.items(.data);
3138 defer scalar_cases_payload.deinit(gpa);
3139 // Same deal, but this is only the `extra` data for the multi cases.
3140 var multi_cases_payload = ArrayListUnmanaged(u32){};
3141 defer multi_cases_payload.deinit(gpa);
31423312
3313 // The struct_decl instruction introduces a scope in which the decls of the struct
3314 // are in scope, so that field types, alignments, and default value expressions
3315 // can refer to decls within the struct itself.
3143 var block_scope: GenZir = .{3316 var block_scope: GenZir = .{
3144 .parent = scope,3317 .parent = scope,
3318 .decl_node_index = node,
3319 .decl_line = gz.calcLine(node),
3145 .astgen = astgen,3320 .astgen = astgen,
3146 .force_comptime = parent_gz.force_comptime,3321 .force_comptime = true,
3147 .instructions = .{},3322 .ref_start_index = gz.ref_start_index,
3148 };3323 };
3149 block_scope.setBreakResultLoc(rl);
3150 defer block_scope.instructions.deinit(gpa);3324 defer block_scope.instructions.deinit(gpa);
31513325
3152 // This gets added to the parent block later, after the item expressions.3326 var namespace: Scope.Namespace = .{ .parent = &gz.base };
3153 const switch_block = try parent_gz.addBlock(undefined, switch_node);3327 defer namespace.decls.deinit(gpa);
31543328
3155 // We re-use this same scope for all cases, including the special prong, if any.3329 var wip_decls: WipDecls = .{};
3156 var case_scope: GenZir = .{3330 defer wip_decls.deinit(gpa);
3157 .parent = &block_scope.base,3331
3158 .astgen = astgen,3332 // We don't know which members are fields until we iterate, so cannot do
3159 .force_comptime = parent_gz.force_comptime,3333 // an accurate ensureCapacity yet.
3160 .instructions = .{},3334 var fields_data = ArrayListUnmanaged(u32){};
3161 };3335 defer fields_data.deinit(gpa);
3162 defer case_scope.instructions.deinit(gpa);3336
31633337 const bits_per_field = 4;
3164 // Do the else/`_` first because it goes first in the payload.3338 const fields_per_u32 = 32 / bits_per_field;
3165 var capture_val_scope: Scope.LocalVal = undefined;3339 // We only need this if there are greater than fields_per_u32 fields.
3166 if (special_node != 0) {3340 var bit_bag = ArrayListUnmanaged(u32){};
3167 const case = switch (node_tags[special_node]) {3341 defer bit_bag.deinit(gpa);
3168 .switch_case_one => tree.switchCaseOne(special_node),3342
3169 .switch_case => tree.switchCase(special_node),3343 var cur_bit_bag: u32 = 0;
3170 else => unreachable,3344 var field_index: usize = 0;
3171 };3345 for (container_decl.ast.members) |member_node| {
3172 const sub_scope = blk: {3346 const member = switch (node_tags[member_node]) {
3173 const payload_token = case.payload_token orelse break :blk &case_scope.base;3347 .container_field_init => tree.containerFieldInit(member_node),
3174 const ident = if (token_tags[payload_token] == .asterisk)3348 .container_field_align => tree.containerFieldAlign(member_node),
3175 payload_token + 13349 .container_field => tree.containerField(member_node),
3176 else3350
3177 payload_token;3351 .fn_decl => {
3178 const is_ptr = ident != payload_token;3352 const fn_proto = node_datas[member_node].lhs;
3179 if (mem.eql(u8, tree.tokenSlice(ident), "_")) {3353 const body = node_datas[member_node].rhs;
3180 if (is_ptr) {3354 switch (node_tags[fn_proto]) {
3181 return mod.failTok(&case_scope.base, payload_token, "pointer modifier invalid on discard", .{});3355 .fn_proto_simple => {
3356 var params: [1]ast.Node.Index = undefined;
3357 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
3358 error.OutOfMemory => return error.OutOfMemory,
3359 error.AnalysisFail => {},
3360 };
3361 continue;
3362 },
3363 .fn_proto_multi => {
3364 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
3365 error.OutOfMemory => return error.OutOfMemory,
3366 error.AnalysisFail => {},
3367 };
3368 continue;
3369 },
3370 .fn_proto_one => {
3371 var params: [1]ast.Node.Index = undefined;
3372 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
3373 error.OutOfMemory => return error.OutOfMemory,
3374 error.AnalysisFail => {},
3375 };
3376 continue;
3377 },
3378 .fn_proto => {
3379 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
3380 error.OutOfMemory => return error.OutOfMemory,
3381 error.AnalysisFail => {},
3382 };
3383 continue;
3384 },
3385 else => unreachable,
3182 }3386 }
3183 break :blk &case_scope.base;3387 },
3184 }3388 .fn_proto_simple => {
3185 const capture_tag: zir.Inst.Tag = if (is_ptr)3389 var params: [1]ast.Node.Index = undefined;
3186 .switch_capture_else_ref3390 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
3187 else3391 error.OutOfMemory => return error.OutOfMemory,
3188 .switch_capture_else;3392 error.AnalysisFail => {},
3189 const capture = try case_scope.add(.{3393 };
3190 .tag = capture_tag,3394 continue;
3191 .data = .{ .switch_capture = .{3395 },
3192 .switch_inst = switch_block,3396 .fn_proto_multi => {
3193 .prong_index = undefined,3397 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
3194 } },3398 error.OutOfMemory => return error.OutOfMemory,
3195 });3399 error.AnalysisFail => {},
3196 const capture_name = try mod.identifierTokenString(&parent_gz.base, payload_token);3400 };
3197 capture_val_scope = .{3401 continue;
3198 .parent = &case_scope.base,3402 },
3199 .gen_zir = &case_scope,3403 .fn_proto_one => {
3200 .name = capture_name,3404 var params: [1]ast.Node.Index = undefined;
3201 .inst = capture,3405 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
3202 .src = parent_gz.tokSrcLoc(payload_token),3406 error.OutOfMemory => return error.OutOfMemory,
3203 };3407 error.AnalysisFail => {},
3204 break :blk &capture_val_scope.base;3408 };
3409 continue;
3410 },
3411 .fn_proto => {
3412 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
3413 error.OutOfMemory => return error.OutOfMemory,
3414 error.AnalysisFail => {},
3415 };
3416 continue;
3417 },
3418
3419 .global_var_decl => {
3420 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
3421 error.OutOfMemory => return error.OutOfMemory,
3422 error.AnalysisFail => {},
3423 };
3424 continue;
3425 },
3426 .local_var_decl => {
3427 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
3428 error.OutOfMemory => return error.OutOfMemory,
3429 error.AnalysisFail => {},
3430 };
3431 continue;
3432 },
3433 .simple_var_decl => {
3434 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
3435 error.OutOfMemory => return error.OutOfMemory,
3436 error.AnalysisFail => {},
3437 };
3438 continue;
3439 },
3440 .aligned_var_decl => {
3441 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
3442 error.OutOfMemory => return error.OutOfMemory,
3443 error.AnalysisFail => {},
3444 };
3445 continue;
3446 },
3447
3448 .@"comptime" => {
3449 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3450 error.OutOfMemory => return error.OutOfMemory,
3451 error.AnalysisFail => {},
3452 };
3453 continue;
3454 },
3455 .@"usingnamespace" => {
3456 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3457 error.OutOfMemory => return error.OutOfMemory,
3458 error.AnalysisFail => {},
3459 };
3460 continue;
3461 },
3462 .test_decl => {
3463 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3464 error.OutOfMemory => return error.OutOfMemory,
3465 error.AnalysisFail => {},
3466 };
3467 continue;
3468 },
3469 else => unreachable,
3205 };3470 };
3206 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);3471 if (field_index % fields_per_u32 == 0 and field_index != 0) {
3207 if (!astgen.refIsNoReturn(case_result)) {3472 try bit_bag.append(gpa, cur_bit_bag);
3208 block_scope.break_count += 1;3473 cur_bit_bag = 0;
3209 _ = try case_scope.addBreak(.@"break", switch_block, case_result);
3210 }3474 }
3211 // Documentation for this: `zir.Inst.SwitchBlock` and `zir.Inst.SwitchBlockMulti`.3475 try fields_data.ensureUnusedCapacity(gpa, 4);
3212 try scalar_cases_payload.ensureCapacity(gpa, scalar_cases_payload.items.len +3476
3213 3 + // operand, scalar_cases_len, else body len3477 const field_name = try astgen.identAsString(member.ast.name_token);
3214 @boolToInt(multi_cases_len != 0) +3478 fields_data.appendAssumeCapacity(field_name);
3215 case_scope.instructions.items.len);3479
3216 scalar_cases_payload.appendAssumeCapacity(@enumToInt(operand));3480 const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")
3217 scalar_cases_payload.appendAssumeCapacity(scalar_cases_len);3481 .none
3218 if (multi_cases_len != 0) {3482 else
3219 scalar_cases_payload.appendAssumeCapacity(multi_cases_len);3483 try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);
3484 fields_data.appendAssumeCapacity(@enumToInt(field_type));
3485
3486 const have_align = member.ast.align_expr != 0;
3487 const have_value = member.ast.value_expr != 0;
3488 const is_comptime = member.comptime_token != null;
3489 const unused = false;
3490 cur_bit_bag = (cur_bit_bag >> bits_per_field) |
3491 (@as(u32, @boolToInt(have_align)) << 28) |
3492 (@as(u32, @boolToInt(have_value)) << 29) |
3493 (@as(u32, @boolToInt(is_comptime)) << 30) |
3494 (@as(u32, @boolToInt(unused)) << 31);
3495
3496 if (have_align) {
3497 const align_inst = try expr(&block_scope, &block_scope.base, align_rl, member.ast.align_expr);
3498 fields_data.appendAssumeCapacity(@enumToInt(align_inst));
3220 }3499 }
3221 scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len));3500 if (have_value) {
3222 scalar_cases_payload.appendSliceAssumeCapacity(case_scope.instructions.items);3501 const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type };
3223 } else {3502
3224 // Documentation for this: `zir.Inst.SwitchBlock` and `zir.Inst.SwitchBlockMulti`.3503 const default_inst = try expr(&block_scope, &block_scope.base, rl, member.ast.value_expr);
3225 try scalar_cases_payload.ensureCapacity(gpa, scalar_cases_payload.items.len +3504 fields_data.appendAssumeCapacity(@enumToInt(default_inst));
3226 2 + // operand, scalar_cases_len3505 } else if (member.comptime_token) |comptime_token| {
3227 @boolToInt(multi_cases_len != 0));3506 return astgen.failTok(comptime_token, "comptime field without default initialization value", .{});
3228 scalar_cases_payload.appendAssumeCapacity(@enumToInt(operand));3507 }
3229 scalar_cases_payload.appendAssumeCapacity(scalar_cases_len);3508
3230 if (multi_cases_len != 0) {3509 field_index += 1;
3231 scalar_cases_payload.appendAssumeCapacity(multi_cases_len);3510 }
3511 {
3512 const empty_slot_count = fields_per_u32 - (field_index % fields_per_u32);
3513 if (empty_slot_count < fields_per_u32) {
3514 cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_field);
3515 }
3516 }
3517 {
3518 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
3519 if (empty_slot_count < WipDecls.fields_per_u32) {
3520 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
3232 }3521 }
3233 }3522 }
32343523
3235 // In this pass we generate all the item and prong expressions except the special case.3524 const decl_inst = try gz.reserveInstructionIndex();
3236 var multi_case_index: u32 = 0;3525 if (block_scope.instructions.items.len != 0) {
3237 var scalar_case_index: u32 = 0;3526 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
3238 for (case_nodes) |case_node| {3527 }
3239 if (case_node == special_node)
3240 continue;
3241 const case = switch (node_tags[case_node]) {
3242 .switch_case_one => tree.switchCaseOne(case_node),
3243 .switch_case => tree.switchCase(case_node),
3244 else => unreachable,
3245 };
32463528
3247 // Reset the scope.3529 try gz.setStruct(decl_inst, .{
3248 case_scope.instructions.shrinkRetainingCapacity(0);3530 .src_node = node,
3531 .layout = layout,
3532 .body_len = @intCast(u32, block_scope.instructions.items.len),
3533 .fields_len = @intCast(u32, field_index),
3534 .decls_len = @intCast(u32, wip_decls.decl_index),
3535 });
32493536
3250 const is_multi_case = case.ast.values.len != 1 or3537 try astgen.extra.ensureUnusedCapacity(gpa, bit_bag.items.len +
3251 getRangeNode(node_tags, node_datas, case.ast.values[0]) != null;3538 @boolToInt(field_index != 0) + fields_data.items.len +
3539 block_scope.instructions.items.len +
3540 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
3541 wip_decls.payload.items.len);
3542 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
3543 if (wip_decls.decl_index != 0) {
3544 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
3545 }
3546 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
32523547
3253 const sub_scope = blk: {3548 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
3254 const payload_token = case.payload_token orelse break :blk &case_scope.base;
3255 const ident = if (token_tags[payload_token] == .asterisk)
3256 payload_token + 1
3257 else
3258 payload_token;
3259 const is_ptr = ident != payload_token;
3260 if (mem.eql(u8, tree.tokenSlice(ident), "_")) {
3261 if (is_ptr) {
3262 return mod.failTok(&case_scope.base, payload_token, "pointer modifier invalid on discard", .{});
3263 }
3264 break :blk &case_scope.base;
3265 }
3266 const is_multi_case_bits: u2 = @boolToInt(is_multi_case);
3267 const is_ptr_bits: u2 = @boolToInt(is_ptr);
3268 const capture_tag: zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) {
3269 0b00 => .switch_capture,
3270 0b01 => .switch_capture_ref,
3271 0b10 => .switch_capture_multi,
3272 0b11 => .switch_capture_multi_ref,
3273 };
3274 const capture_index = if (is_multi_case) ci: {
3275 multi_case_index += 1;
3276 break :ci multi_case_index - 1;
3277 } else ci: {
3278 scalar_case_index += 1;
3279 break :ci scalar_case_index - 1;
3280 };
3281 const capture = try case_scope.add(.{
3282 .tag = capture_tag,
3283 .data = .{ .switch_capture = .{
3284 .switch_inst = switch_block,
3285 .prong_index = capture_index,
3286 } },
3287 });
3288 const capture_name = try mod.identifierTokenString(&parent_gz.base, payload_token);
3289 capture_val_scope = .{
3290 .parent = &case_scope.base,
3291 .gen_zir = &case_scope,
3292 .name = capture_name,
3293 .inst = capture,
3294 .src = parent_gz.tokSrcLoc(payload_token),
3295 };
3296 break :blk &capture_val_scope.base;
3297 };
32983549
3299 if (is_multi_case) {3550 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
3300 // items_len, ranges_len, body_len3551 if (field_index != 0) {
3301 const header_index = multi_cases_payload.items.len;3552 astgen.extra.appendAssumeCapacity(cur_bit_bag);
3302 try multi_cases_payload.resize(gpa, multi_cases_payload.items.len + 3);3553 }
3554 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
33033555
3304 // items3556 return gz.indexToRef(decl_inst);
3305 var items_len: u32 = 0;3557}
3306 for (case.ast.values) |item_node| {
3307 if (getRangeNode(node_tags, node_datas, item_node) != null) continue;
3308 items_len += 1;
33093558
3310 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);3559fn unionDeclInner(
3311 try multi_cases_payload.append(gpa, @enumToInt(item_inst));3560 gz: *GenZir,
3312 }3561 scope: *Scope,
3562 node: ast.Node.Index,
3563 members: []const ast.Node.Index,
3564 layout: std.builtin.TypeInfo.ContainerLayout,
3565 arg_inst: Zir.Inst.Ref,
3566 have_auto_enum: bool,
3567) InnerError!Zir.Inst.Ref {
3568 const astgen = gz.astgen;
3569 const gpa = astgen.gpa;
3570 const tree = astgen.tree;
3571 const node_tags = tree.nodes.items(.tag);
3572 const node_datas = tree.nodes.items(.data);
33133573
3314 // ranges3574 // The union_decl instruction introduces a scope in which the decls of the union
3315 var ranges_len: u32 = 0;3575 // are in scope, so that field types, alignments, and default value expressions
3316 for (case.ast.values) |item_node| {3576 // can refer to decls within the union itself.
3317 const range = getRangeNode(node_tags, node_datas, item_node) orelse continue;3577 var block_scope: GenZir = .{
3318 ranges_len += 1;3578 .parent = scope,
3579 .decl_node_index = node,
3580 .decl_line = gz.calcLine(node),
3581 .astgen = astgen,
3582 .force_comptime = true,
3583 .ref_start_index = gz.ref_start_index,
3584 };
3585 defer block_scope.instructions.deinit(gpa);
33193586
3320 const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs);3587 var namespace: Scope.Namespace = .{ .parent = &gz.base };
3321 const last = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].rhs);3588 defer namespace.decls.deinit(gpa);
3322 try multi_cases_payload.appendSlice(gpa, &[_]u32{3589
3323 @enumToInt(first), @enumToInt(last),3590 var wip_decls: WipDecls = .{};
3324 });3591 defer wip_decls.deinit(gpa);
3325 }3592
3593 // We don't know which members are fields until we iterate, so cannot do
3594 // an accurate ensureCapacity yet.
3595 var fields_data = ArrayListUnmanaged(u32){};
3596 defer fields_data.deinit(gpa);
3597
3598 const bits_per_field = 4;
3599 const fields_per_u32 = 32 / bits_per_field;
3600 // We only need this if there are greater than fields_per_u32 fields.
3601 var bit_bag = ArrayListUnmanaged(u32){};
3602 defer bit_bag.deinit(gpa);
3603
3604 var cur_bit_bag: u32 = 0;
3605 var field_index: usize = 0;
3606 for (members) |member_node| {
3607 const member = switch (node_tags[member_node]) {
3608 .container_field_init => tree.containerFieldInit(member_node),
3609 .container_field_align => tree.containerFieldAlign(member_node),
3610 .container_field => tree.containerField(member_node),
3611
3612 .fn_decl => {
3613 const fn_proto = node_datas[member_node].lhs;
3614 const body = node_datas[member_node].rhs;
3615 switch (node_tags[fn_proto]) {
3616 .fn_proto_simple => {
3617 var params: [1]ast.Node.Index = undefined;
3618 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
3619 error.OutOfMemory => return error.OutOfMemory,
3620 error.AnalysisFail => {},
3621 };
3622 continue;
3623 },
3624 .fn_proto_multi => {
3625 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
3626 error.OutOfMemory => return error.OutOfMemory,
3627 error.AnalysisFail => {},
3628 };
3629 continue;
3630 },
3631 .fn_proto_one => {
3632 var params: [1]ast.Node.Index = undefined;
3633 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
3634 error.OutOfMemory => return error.OutOfMemory,
3635 error.AnalysisFail => {},
3636 };
3637 continue;
3638 },
3639 .fn_proto => {
3640 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
3641 error.OutOfMemory => return error.OutOfMemory,
3642 error.AnalysisFail => {},
3643 };
3644 continue;
3645 },
3646 else => unreachable,
3647 }
3648 },
3649 .fn_proto_simple => {
3650 var params: [1]ast.Node.Index = undefined;
3651 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
3652 error.OutOfMemory => return error.OutOfMemory,
3653 error.AnalysisFail => {},
3654 };
3655 continue;
3656 },
3657 .fn_proto_multi => {
3658 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
3659 error.OutOfMemory => return error.OutOfMemory,
3660 error.AnalysisFail => {},
3661 };
3662 continue;
3663 },
3664 .fn_proto_one => {
3665 var params: [1]ast.Node.Index = undefined;
3666 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
3667 error.OutOfMemory => return error.OutOfMemory,
3668 error.AnalysisFail => {},
3669 };
3670 continue;
3671 },
3672 .fn_proto => {
3673 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
3674 error.OutOfMemory => return error.OutOfMemory,
3675 error.AnalysisFail => {},
3676 };
3677 continue;
3678 },
33263679
3327 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);3680 .global_var_decl => {
3328 if (!astgen.refIsNoReturn(case_result)) {3681 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
3329 block_scope.break_count += 1;3682 error.OutOfMemory => return error.OutOfMemory,
3330 _ = try case_scope.addBreak(.@"break", switch_block, case_result);3683 error.AnalysisFail => {},
3684 };
3685 continue;
3686 },
3687 .local_var_decl => {
3688 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
3689 error.OutOfMemory => return error.OutOfMemory,
3690 error.AnalysisFail => {},
3691 };
3692 continue;
3693 },
3694 .simple_var_decl => {
3695 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
3696 error.OutOfMemory => return error.OutOfMemory,
3697 error.AnalysisFail => {},
3698 };
3699 continue;
3700 },
3701 .aligned_var_decl => {
3702 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
3703 error.OutOfMemory => return error.OutOfMemory,
3704 error.AnalysisFail => {},
3705 };
3706 continue;
3707 },
3708
3709 .@"comptime" => {
3710 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3711 error.OutOfMemory => return error.OutOfMemory,
3712 error.AnalysisFail => {},
3713 };
3714 continue;
3715 },
3716 .@"usingnamespace" => {
3717 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3718 error.OutOfMemory => return error.OutOfMemory,
3719 error.AnalysisFail => {},
3720 };
3721 continue;
3722 },
3723 .test_decl => {
3724 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3725 error.OutOfMemory => return error.OutOfMemory,
3726 error.AnalysisFail => {},
3727 };
3728 continue;
3729 },
3730 else => unreachable,
3731 };
3732 if (field_index % fields_per_u32 == 0 and field_index != 0) {
3733 try bit_bag.append(gpa, cur_bit_bag);
3734 cur_bit_bag = 0;
3735 }
3736 if (member.comptime_token) |comptime_token| {
3737 return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
3738 }
3739 try fields_data.ensureUnusedCapacity(gpa, 4);
3740
3741 const field_name = try astgen.identAsString(member.ast.name_token);
3742 fields_data.appendAssumeCapacity(field_name);
3743
3744 const have_type = member.ast.type_expr != 0;
3745 const have_align = member.ast.align_expr != 0;
3746 const have_value = member.ast.value_expr != 0;
3747 const unused = false;
3748 cur_bit_bag = (cur_bit_bag >> bits_per_field) |
3749 (@as(u32, @boolToInt(have_type)) << 28) |
3750 (@as(u32, @boolToInt(have_align)) << 29) |
3751 (@as(u32, @boolToInt(have_value)) << 30) |
3752 (@as(u32, @boolToInt(unused)) << 31);
3753
3754 if (have_type) {
3755 const field_type = try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);
3756 fields_data.appendAssumeCapacity(@enumToInt(field_type));
3757 }
3758 if (have_align) {
3759 const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr);
3760 fields_data.appendAssumeCapacity(@enumToInt(align_inst));
3761 }
3762 if (have_value) {
3763 if (arg_inst == .none) {
3764 return astgen.failNodeNotes(
3765 node,
3766 "explicitly valued tagged union missing integer tag type",
3767 .{},
3768 &[_]u32{
3769 try astgen.errNoteNode(
3770 member.ast.value_expr,
3771 "tag value specified here",
3772 .{},
3773 ),
3774 },
3775 );
3331 }3776 }
3777 const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr);
3778 fields_data.appendAssumeCapacity(@enumToInt(tag_value));
3779 }
33323780
3333 multi_cases_payload.items[header_index + 0] = items_len;3781 field_index += 1;
3334 multi_cases_payload.items[header_index + 1] = ranges_len;3782 }
3335 multi_cases_payload.items[header_index + 2] = @intCast(u32, case_scope.instructions.items.len);3783 if (field_index == 0) {
3336 try multi_cases_payload.appendSlice(gpa, case_scope.instructions.items);3784 return astgen.failNode(node, "union declarations must have at least one tag", .{});
3337 } else {3785 }
3338 const item_node = case.ast.values[0];3786 {
3339 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);3787 const empty_slot_count = fields_per_u32 - (field_index % fields_per_u32);
3340 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);3788 if (empty_slot_count < fields_per_u32) {
3341 if (!astgen.refIsNoReturn(case_result)) {3789 cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_field);
3342 block_scope.break_count += 1;3790 }
3343 _ = try case_scope.addBreak(.@"break", switch_block, case_result);3791 }
3344 }3792 {
3345 try scalar_cases_payload.ensureCapacity(gpa, scalar_cases_payload.items.len +3793 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
3346 2 + case_scope.instructions.items.len);3794 if (empty_slot_count < WipDecls.fields_per_u32) {
3347 scalar_cases_payload.appendAssumeCapacity(@enumToInt(item_inst));3795 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
3348 scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len));
3349 scalar_cases_payload.appendSliceAssumeCapacity(case_scope.instructions.items);
3350 }3796 }
3351 }3797 }
3352 // Now that the item expressions are generated we can add this.
3353 try parent_gz.instructions.append(gpa, switch_block);
33543798
3355 const ref_bit: u4 = @boolToInt(any_payload_is_ref);3799 const decl_inst = try gz.reserveInstructionIndex();
3356 const multi_bit: u4 = @boolToInt(multi_cases_len != 0);3800 if (block_scope.instructions.items.len != 0) {
3357 const special_prong_bits: u4 = @enumToInt(special_prong);3801 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
3358 comptime {
3359 assert(@enumToInt(zir.SpecialProng.none) == 0b00);
3360 assert(@enumToInt(zir.SpecialProng.@"else") == 0b01);
3361 assert(@enumToInt(zir.SpecialProng.under) == 0b10);
3362 }3802 }
3363 const zir_tags = astgen.instructions.items(.tag);
3364 zir_tags[switch_block] = switch ((ref_bit << 3) | (special_prong_bits << 1) | multi_bit) {
3365 0b0_00_0 => .switch_block,
3366 0b0_00_1 => .switch_block_multi,
3367 0b0_01_0 => .switch_block_else,
3368 0b0_01_1 => .switch_block_else_multi,
3369 0b0_10_0 => .switch_block_under,
3370 0b0_10_1 => .switch_block_under_multi,
3371 0b1_00_0 => .switch_block_ref,
3372 0b1_00_1 => .switch_block_ref_multi,
3373 0b1_01_0 => .switch_block_ref_else,
3374 0b1_01_1 => .switch_block_ref_else_multi,
3375 0b1_10_0 => .switch_block_ref_under,
3376 0b1_10_1 => .switch_block_ref_under_multi,
3377 else => unreachable,
3378 };
3379 const payload_index = astgen.extra.items.len;
3380 const zir_datas = astgen.instructions.items(.data);
3381 zir_datas[switch_block].pl_node.payload_index = @intCast(u32, payload_index);
3382 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
3383 scalar_cases_payload.items.len + multi_cases_payload.items.len);
3384 const strat = rl.strategy(&block_scope);
3385 switch (strat.tag) {
3386 .break_operand => {
3387 // Switch expressions return `true` for `nodeMayNeedMemoryLocation` thus
3388 // `elide_store_to_block_ptr_instructions` will either be true,
3389 // or all prongs are noreturn.
3390 if (!strat.elide_store_to_block_ptr_instructions) {
3391 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items);
3392 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items);
3393 return astgen.indexToRef(switch_block);
3394 }
33953803
3396 // There will necessarily be a store_to_block_ptr for3804 try gz.setUnion(decl_inst, .{
3397 // all prongs, except for prongs that ended with a noreturn instruction.3805 .src_node = node,
3398 // Elide all the `store_to_block_ptr` instructions.3806 .layout = layout,
3807 .tag_type = arg_inst,
3808 .body_len = @intCast(u32, block_scope.instructions.items.len),
3809 .fields_len = @intCast(u32, field_index),
3810 .decls_len = @intCast(u32, wip_decls.decl_index),
3811 .auto_enum_tag = have_auto_enum,
3812 });
33993813
3400 // The break instructions need to have their operands coerced if the3814 try astgen.extra.ensureUnusedCapacity(gpa, bit_bag.items.len +
3401 // switch's result location is a `ty`. In this case we overwrite the3815 1 + fields_data.items.len +
3402 // `store_to_block_ptr` instruction with an `as` instruction and repurpose3816 block_scope.instructions.items.len +
3403 // it as the break operand.3817 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
3818 wip_decls.payload.items.len);
3819 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
3820 if (wip_decls.decl_index != 0) {
3821 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
3822 }
3823 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
34043824
3405 var extra_index: usize = 0;3825 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
3406 extra_index += 2;
3407 extra_index += @boolToInt(multi_cases_len != 0);
3408 if (special_prong != .none) special_prong: {
3409 const body_len_index = extra_index;
3410 const body_len = scalar_cases_payload.items[extra_index];
3411 extra_index += 1;
3412 if (body_len < 2) {
3413 extra_index += body_len;
3414 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]);
3415 break :special_prong;
3416 }
3417 extra_index += body_len - 2;
3418 const store_inst = scalar_cases_payload.items[extra_index];
3419 if (zir_tags[store_inst] != .store_to_block_ptr) {
3420 extra_index += 2;
3421 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]);
3422 break :special_prong;
3423 }
3424 assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr);
3425 if (block_scope.rl_ty_inst != .none) {
3426 extra_index += 1;
3427 const break_inst = scalar_cases_payload.items[extra_index];
3428 extra_index += 1;
3429 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]);
3430 zir_tags[store_inst] = .as;
3431 zir_datas[store_inst].bin = .{
3432 .lhs = block_scope.rl_ty_inst,
3433 .rhs = zir_datas[break_inst].@"break".operand,
3434 };
3435 zir_datas[break_inst].@"break".operand = astgen.indexToRef(store_inst);
3436 } else {
3437 scalar_cases_payload.items[body_len_index] -= 1;
3438 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]);
3439 extra_index += 1;
3440 astgen.extra.appendAssumeCapacity(scalar_cases_payload.items[extra_index]);
3441 extra_index += 1;
3442 }
3443 } else {
3444 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]);
3445 }
3446 var scalar_i: u32 = 0;
3447 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
3448 const start_index = extra_index;
3449 extra_index += 1;
3450 const body_len_index = extra_index;
3451 const body_len = scalar_cases_payload.items[extra_index];
3452 extra_index += 1;
3453 if (body_len < 2) {
3454 extra_index += body_len;
3455 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
3456 continue;
3457 }
3458 extra_index += body_len - 2;
3459 const store_inst = scalar_cases_payload.items[extra_index];
3460 if (zir_tags[store_inst] != .store_to_block_ptr) {
3461 extra_index += 2;
3462 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
3463 continue;
3464 }
3465 if (block_scope.rl_ty_inst != .none) {
3466 extra_index += 1;
3467 const break_inst = scalar_cases_payload.items[extra_index];
3468 extra_index += 1;
3469 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
3470 zir_tags[store_inst] = .as;
3471 zir_datas[store_inst].bin = .{
3472 .lhs = block_scope.rl_ty_inst,
3473 .rhs = zir_datas[break_inst].@"break".operand,
3474 };
3475 zir_datas[break_inst].@"break".operand = astgen.indexToRef(store_inst);
3476 } else {
3477 assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr);
3478 scalar_cases_payload.items[body_len_index] -= 1;
3479 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
3480 extra_index += 1;
3481 astgen.extra.appendAssumeCapacity(scalar_cases_payload.items[extra_index]);
3482 extra_index += 1;
3483 }
3484 }
3485 extra_index = 0;
3486 var multi_i: u32 = 0;
3487 while (multi_i < multi_cases_len) : (multi_i += 1) {
3488 const start_index = extra_index;
3489 const items_len = multi_cases_payload.items[extra_index];
3490 extra_index += 1;
3491 const ranges_len = multi_cases_payload.items[extra_index];
3492 extra_index += 1;
3493 const body_len_index = extra_index;
3494 const body_len = multi_cases_payload.items[extra_index];
3495 extra_index += 1;
3496 extra_index += items_len;
3497 extra_index += 2 * ranges_len;
3498 if (body_len < 2) {
3499 extra_index += body_len;
3500 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
3501 continue;
3502 }
3503 extra_index += body_len - 2;
3504 const store_inst = multi_cases_payload.items[extra_index];
3505 if (zir_tags[store_inst] != .store_to_block_ptr) {
3506 extra_index += 2;
3507 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
3508 continue;
3509 }
3510 if (block_scope.rl_ty_inst != .none) {
3511 extra_index += 1;
3512 const break_inst = multi_cases_payload.items[extra_index];
3513 extra_index += 1;
3514 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
3515 zir_tags[store_inst] = .as;
3516 zir_datas[store_inst].bin = .{
3517 .lhs = block_scope.rl_ty_inst,
3518 .rhs = zir_datas[break_inst].@"break".operand,
3519 };
3520 zir_datas[break_inst].@"break".operand = astgen.indexToRef(store_inst);
3521 } else {
3522 assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr);
3523 multi_cases_payload.items[body_len_index] -= 1;
3524 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
3525 extra_index += 1;
3526 astgen.extra.appendAssumeCapacity(multi_cases_payload.items[extra_index]);
3527 extra_index += 1;
3528 }
3529 }
35303826
3531 const block_ref = astgen.indexToRef(switch_block);3827 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
3532 switch (rl) {3828 astgen.extra.appendAssumeCapacity(cur_bit_bag);
3533 .ref => return block_ref,3829 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
3534 else => return rvalue(parent_gz, scope, rl, block_ref, switch_node),
3535 }
3536 },
3537 .break_void => {
3538 assert(!strat.elide_store_to_block_ptr_instructions);
3539 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items);
3540 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items);
3541 // Modify all the terminating instruction tags to become `break` variants.
3542 var extra_index: usize = payload_index;
3543 extra_index += 2;
3544 extra_index += @boolToInt(multi_cases_len != 0);
3545 if (special_prong != .none) {
3546 const body_len = astgen.extra.items[extra_index];
3547 extra_index += 1;
3548 const body = astgen.extra.items[extra_index..][0..body_len];
3549 extra_index += body_len;
3550 const last = body[body.len - 1];
3551 if (zir_tags[last] == .@"break" and
3552 zir_datas[last].@"break".block_inst == switch_block)
3553 {
3554 zir_datas[last].@"break".operand = .void_value;
3555 }
3556 }
3557 var scalar_i: u32 = 0;
3558 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
3559 extra_index += 1;
3560 const body_len = astgen.extra.items[extra_index];
3561 extra_index += 1;
3562 const body = astgen.extra.items[extra_index..][0..body_len];
3563 extra_index += body_len;
3564 const last = body[body.len - 1];
3565 if (zir_tags[last] == .@"break" and
3566 zir_datas[last].@"break".block_inst == switch_block)
3567 {
3568 zir_datas[last].@"break".operand = .void_value;
3569 }
3570 }
3571 var multi_i: u32 = 0;
3572 while (multi_i < multi_cases_len) : (multi_i += 1) {
3573 const items_len = astgen.extra.items[extra_index];
3574 extra_index += 1;
3575 const ranges_len = astgen.extra.items[extra_index];
3576 extra_index += 1;
3577 const body_len = astgen.extra.items[extra_index];
3578 extra_index += 1;
3579 extra_index += items_len;
3580 extra_index += 2 * ranges_len;
3581 const body = astgen.extra.items[extra_index..][0..body_len];
3582 extra_index += body_len;
3583 const last = body[body.len - 1];
3584 if (zir_tags[last] == .@"break" and
3585 zir_datas[last].@"break".block_inst == switch_block)
3586 {
3587 zir_datas[last].@"break".operand = .void_value;
3588 }
3589 }
35903830
3591 return astgen.indexToRef(switch_block);3831 return gz.indexToRef(decl_inst);
3592 },
3593 }
3594}3832}
35953833
3596fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {3834fn containerDecl(
3597 const tree = gz.tree();3835 gz: *GenZir,
3836 scope: *Scope,
3837 rl: ResultLoc,
3838 node: ast.Node.Index,
3839 container_decl: ast.full.ContainerDecl,
3840) InnerError!Zir.Inst.Ref {
3841 const astgen = gz.astgen;
3842 const gpa = astgen.gpa;
3843 const tree = astgen.tree;
3844 const token_tags = tree.tokens.items(.tag);
3845 const node_tags = tree.nodes.items(.tag);
3598 const node_datas = tree.nodes.items(.data);3846 const node_datas = tree.nodes.items(.data);
3599 const main_tokens = tree.nodes.items(.main_token);
36003847
3601 const operand_node = node_datas[node].lhs;3848 // We must not create any types until Sema. Here the goal is only to generate
3602 const operand: zir.Inst.Ref = if (operand_node != 0) operand: {3849 // ZIR for all the field types, alignments, and default value expressions.
3603 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node)) .{
3604 .ptr = try gz.addNode(.ret_ptr, node),
3605 } else .{
3606 .ty = try gz.addNode(.ret_type, node),
3607 };
3608 break :operand try expr(gz, scope, rl, operand_node);
3609 } else .void_value;
3610 _ = try gz.addUnNode(.ret_node, operand, node);
3611 return zir.Inst.Ref.unreachable_value;
3612}
36133850
3614fn identifier(3851 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
3615 gz: *GenZir,3852 try comptimeExpr(gz, scope, .{ .ty = .type_type }, container_decl.ast.arg)
3616 scope: *Scope,3853 else
3617 rl: ResultLoc,3854 .none;
3618 ident: ast.Node.Index,
3619) InnerError!zir.Inst.Ref {
3620 const tracy = trace(@src());
3621 defer tracy.end();
36223855
3623 const astgen = gz.astgen;3856 switch (token_tags[container_decl.ast.main_token]) {
3624 const mod = astgen.mod;3857 .keyword_struct => {
3625 const tree = gz.tree();3858 const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
3626 const main_tokens = tree.nodes.items(.main_token);3859 .keyword_packed => std.builtin.TypeInfo.ContainerLayout.Packed,
3860 .keyword_extern => std.builtin.TypeInfo.ContainerLayout.Extern,
3861 else => unreachable,
3862 } else std.builtin.TypeInfo.ContainerLayout.Auto;
36273863
3628 const ident_token = main_tokens[ident];3864 assert(arg_inst == .none);
3629 const ident_name = try mod.identifierTokenString(scope, ident_token);
3630 if (mem.eql(u8, ident_name, "_")) {
3631 return mod.failNode(scope, ident, "TODO implement '_' identifier", .{});
3632 }
36333865
3634 if (simple_types.get(ident_name)) |zir_const_ref| {3866 const result = try structDeclInner(gz, scope, node, container_decl, layout);
3635 return rvalue(gz, scope, rl, zir_const_ref, ident);3867 return rvalue(gz, scope, rl, result, node);
3636 }3868 },
3869 .keyword_union => {
3870 const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
3871 .keyword_packed => std.builtin.TypeInfo.ContainerLayout.Packed,
3872 .keyword_extern => std.builtin.TypeInfo.ContainerLayout.Extern,
3873 else => unreachable,
3874 } else std.builtin.TypeInfo.ContainerLayout.Auto;
36373875
3638 if (ident_name.len >= 2) integer: {3876 const have_auto_enum = container_decl.ast.enum_token != null;
3639 const first_c = ident_name[0];
3640 if (first_c == 'i' or first_c == 'u') {
3641 const signedness: std.builtin.Signedness = switch (first_c == 'i') {
3642 true => .signed,
3643 false => .unsigned,
3644 };
3645 const bit_count = std.fmt.parseInt(u16, ident_name[1..], 10) catch |err| switch (err) {
3646 error.Overflow => return mod.failNode(
3647 scope,
3648 ident,
3649 "primitive integer type '{s}' exceeds maximum bit width of 65535",
3650 .{ident_name},
3651 ),
3652 error.InvalidCharacter => break :integer,
3653 };
3654 const result = try gz.add(.{
3655 .tag = .int_type,
3656 .data = .{ .int_type = .{
3657 .src_node = astgen.decl.nodeIndexToRelative(ident),
3658 .signedness = signedness,
3659 .bit_count = bit_count,
3660 } },
3661 });
3662 return rvalue(gz, scope, rl, result, ident);
3663 }
3664 }
36653877
3666 // Local variables, including function parameters.3878 const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, arg_inst, have_auto_enum);
3667 {3879 return rvalue(gz, scope, rl, result, node);
3668 var s = scope;3880 },
3669 while (true) switch (s.tag) {3881 .keyword_enum => {
3670 .local_val => {3882 if (container_decl.layout_token) |t| {
3671 const local_val = s.cast(Scope.LocalVal).?;3883 return astgen.failTok(t, "enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type", .{});
3672 if (mem.eql(u8, local_val.name, ident_name)) {3884 }
3673 return rvalue(gz, scope, rl, local_val.inst, ident);3885 // Count total fields as well as how many have explicitly provided tag values.
3674 }3886 const counts = blk: {
3675 s = local_val.parent;3887 var values: usize = 0;
3676 },3888 var total_fields: usize = 0;
3677 .local_ptr => {3889 var decls: usize = 0;
3678 const local_ptr = s.cast(Scope.LocalPtr).?;3890 var nonexhaustive_node: ast.Node.Index = 0;
3679 if (mem.eql(u8, local_ptr.name, ident_name)) {3891 for (container_decl.ast.members) |member_node| {
3680 switch (rl) {3892 const member = switch (node_tags[member_node]) {
3681 .ref, .none_or_ref => return local_ptr.ptr,3893 .container_field_init => tree.containerFieldInit(member_node),
3894 .container_field_align => tree.containerFieldAlign(member_node),
3895 .container_field => tree.containerField(member_node),
3682 else => {3896 else => {
3683 const loaded = try gz.addUnNode(.load, local_ptr.ptr, ident);3897 decls += 1;
3684 return rvalue(gz, scope, rl, loaded, ident);3898 continue;
3685 },3899 },
3900 };
3901 if (member.comptime_token) |comptime_token| {
3902 return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});
3686 }3903 }
3687 }3904 if (member.ast.type_expr != 0) {
3688 s = local_ptr.parent;3905 return astgen.failNode(member.ast.type_expr, "enum fields do not have types", .{});
3689 },3906 }
3690 .gen_zir => s = s.cast(GenZir).?.parent,3907 // Alignment expressions in enums are caught by the parser.
3691 else => break,3908 assert(member.ast.align_expr == 0);
3692 };
3693 }
36943909
3695 const decl = mod.lookupDeclName(scope, ident_name) orelse {3910 const name_token = member.ast.name_token;
3696 // TODO insert a "dependency on the non-existence of a decl" here to make this3911 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
3697 // compile error go away when the decl is introduced. This data should be in a global3912 if (nonexhaustive_node != 0) {
3698 // sparse map since it is only relevant when a compile error occurs.3913 return astgen.failNodeNotes(
3699 return mod.failNode(scope, ident, "use of undeclared identifier '{s}'", .{ident_name});3914 member_node,
3700 };3915 "redundant non-exhaustive enum mark",
3701 const decl_index = try mod.declareDeclDependency(astgen.decl, decl);3916 .{},
3702 switch (rl) {3917 &[_]u32{
3703 .ref, .none_or_ref => return gz.addDecl(.decl_ref, decl_index, ident),3918 try astgen.errNoteNode(
3704 else => return rvalue(gz, scope, rl, try gz.addDecl(.decl_val, decl_index, ident), ident),3919 nonexhaustive_node,
3705 }3920 "other mark here",
3706}3921 .{},
3922 ),
3923 },
3924 );
3925 }
3926 nonexhaustive_node = member_node;
3927 if (member.ast.value_expr != 0) {
3928 return astgen.failNode(member.ast.value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{});
3929 }
3930 continue;
3931 }
3932 total_fields += 1;
3933 if (member.ast.value_expr != 0) {
3934 if (arg_inst == .none) {
3935 return astgen.failNode(member.ast.value_expr, "value assigned to enum tag with inferred tag type", .{});
3936 }
3937 values += 1;
3938 }
3939 }
3940 break :blk .{
3941 .total_fields = total_fields,
3942 .values = values,
3943 .decls = decls,
3944 .nonexhaustive_node = nonexhaustive_node,
3945 };
3946 };
3947 if (counts.total_fields == 0) {
3948 // One can construct an enum with no tags, and it functions the same as `noreturn`. But
3949 // this is only useful for generic code; when explicitly using `enum {}` syntax, there
3950 // must be at least one tag.
3951 return astgen.failNode(node, "enum declarations must have at least one tag", .{});
3952 }
3953 if (counts.nonexhaustive_node != 0 and arg_inst == .none) {
3954 return astgen.failNodeNotes(
3955 node,
3956 "non-exhaustive enum missing integer tag type",
3957 .{},
3958 &[_]u32{
3959 try astgen.errNoteNode(
3960 counts.nonexhaustive_node,
3961 "marked non-exhaustive here",
3962 .{},
3963 ),
3964 },
3965 );
3966 }
3967 // In this case we must generate ZIR code for the tag values, similar to
3968 // how structs are handled above.
3969 const nonexhaustive = counts.nonexhaustive_node != 0;
37073970
3708fn stringLiteral(3971 // The enum_decl instruction introduces a scope in which the decls of the enum
3709 gz: *GenZir,3972 // are in scope, so that tag values can refer to decls within the enum itself.
3710 scope: *Scope,3973 var block_scope: GenZir = .{
3711 rl: ResultLoc,3974 .parent = scope,
3712 node: ast.Node.Index,3975 .decl_node_index = node,
3713) InnerError!zir.Inst.Ref {3976 .decl_line = gz.calcLine(node),
3714 const tree = gz.tree();3977 .astgen = astgen,
3715 const main_tokens = tree.nodes.items(.main_token);3978 .force_comptime = true,
3716 const string_bytes = &gz.astgen.string_bytes;3979 .ref_start_index = gz.ref_start_index,
3717 const str_index = string_bytes.items.len;3980 };
3718 const str_lit_token = main_tokens[node];3981 defer block_scope.instructions.deinit(gpa);
3719 const token_bytes = tree.tokenSlice(str_lit_token);
3720 try gz.astgen.mod.parseStrLit(scope, str_lit_token, string_bytes, token_bytes, 0);
3721 const str_len = string_bytes.items.len - str_index;
3722 const result = try gz.add(.{
3723 .tag = .str,
3724 .data = .{ .str = .{
3725 .start = @intCast(u32, str_index),
3726 .len = @intCast(u32, str_len),
3727 } },
3728 });
3729 return rvalue(gz, scope, rl, result, node);
3730}
37313982
3732fn multilineStringLiteral(3983 var namespace: Scope.Namespace = .{ .parent = &gz.base };
3733 gz: *GenZir,3984 defer namespace.decls.deinit(gpa);
3734 scope: *Scope,
3735 rl: ResultLoc,
3736 node: ast.Node.Index,
3737) InnerError!zir.Inst.Ref {
3738 const tree = gz.tree();
3739 const node_datas = tree.nodes.items(.data);
3740 const main_tokens = tree.nodes.items(.main_token);
37413985
3742 const start = node_datas[node].lhs;3986 var wip_decls: WipDecls = .{};
3743 const end = node_datas[node].rhs;3987 defer wip_decls.deinit(gpa);
37443988
3745 const gpa = gz.astgen.mod.gpa;3989 var fields_data = ArrayListUnmanaged(u32){};
3746 const string_bytes = &gz.astgen.string_bytes;3990 defer fields_data.deinit(gpa);
3747 const str_index = string_bytes.items.len;
37483991
3749 // First line: do not append a newline.3992 try fields_data.ensureCapacity(gpa, counts.total_fields + counts.values);
3750 var tok_i = start;
3751 {
3752 const slice = tree.tokenSlice(tok_i);
3753 const line_bytes = slice[2 .. slice.len - 1];
3754 try string_bytes.appendSlice(gpa, line_bytes);
3755 tok_i += 1;
3756 }
3757 // Following lines: each line prepends a newline.
3758 while (tok_i <= end) : (tok_i += 1) {
3759 const slice = tree.tokenSlice(tok_i);
3760 const line_bytes = slice[2 .. slice.len - 1];
3761 try string_bytes.ensureCapacity(gpa, string_bytes.items.len + line_bytes.len + 1);
3762 string_bytes.appendAssumeCapacity('\n');
3763 string_bytes.appendSliceAssumeCapacity(line_bytes);
3764 }
3765 const result = try gz.add(.{
3766 .tag = .str,
3767 .data = .{ .str = .{
3768 .start = @intCast(u32, str_index),
3769 .len = @intCast(u32, string_bytes.items.len - str_index),
3770 } },
3771 });
3772 return rvalue(gz, scope, rl, result, node);
3773}
37743993
3775fn charLiteral(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !zir.Inst.Ref {3994 // We only need this if there are greater than 32 fields.
3776 const mod = gz.astgen.mod;3995 var bit_bag = ArrayListUnmanaged(u32){};
3777 const tree = gz.tree();3996 defer bit_bag.deinit(gpa);
3778 const main_tokens = tree.nodes.items(.main_token);
3779 const main_token = main_tokens[node];
3780 const slice = tree.tokenSlice(main_token);
37813997
3782 var bad_index: usize = undefined;3998 var cur_bit_bag: u32 = 0;
3783 const value = std.zig.parseCharLiteral(slice, &bad_index) catch |err| switch (err) {3999 var field_index: usize = 0;
3784 error.InvalidCharacter => {4000 for (container_decl.ast.members) |member_node| {
3785 const bad_byte = slice[bad_index];4001 if (member_node == counts.nonexhaustive_node)
3786 const token_starts = tree.tokens.items(.start);4002 continue;
3787 const src_off = @intCast(u32, token_starts[main_token] + bad_index);4003 const member = switch (node_tags[member_node]) {
3788 return mod.failOff(scope, src_off, "invalid character: '{c}'\n", .{bad_byte});4004 .container_field_init => tree.containerFieldInit(member_node),
3789 },4005 .container_field_align => tree.containerFieldAlign(member_node),
3790 };4006 .container_field => tree.containerField(member_node),
3791 const result = try gz.addInt(value);
3792 return rvalue(gz, scope, rl, result, node);
3793}
37944007
3795fn integerLiteral(4008 .fn_decl => {
3796 gz: *GenZir,4009 const fn_proto = node_datas[member_node].lhs;
3797 scope: *Scope,4010 const body = node_datas[member_node].rhs;
3798 rl: ResultLoc,4011 switch (node_tags[fn_proto]) {
3799 node: ast.Node.Index,4012 .fn_proto_simple => {
3800) InnerError!zir.Inst.Ref {4013 var params: [1]ast.Node.Index = undefined;
3801 const tree = gz.tree();4014 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
3802 const main_tokens = tree.nodes.items(.main_token);4015 error.OutOfMemory => return error.OutOfMemory,
3803 const int_token = main_tokens[node];4016 error.AnalysisFail => {},
3804 const prefixed_bytes = tree.tokenSlice(int_token);4017 };
3805 if (std.fmt.parseInt(u64, prefixed_bytes, 0)) |small_int| {4018 continue;
3806 const result: zir.Inst.Ref = switch (small_int) {4019 },
3807 0 => .zero,4020 .fn_proto_multi => {
3808 1 => .one,4021 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
3809 else => try gz.addInt(small_int),4022 error.OutOfMemory => return error.OutOfMemory,
3810 };4023 error.AnalysisFail => {},
3811 return rvalue(gz, scope, rl, result, node);4024 };
3812 } else |err| {4025 continue;
3813 return gz.astgen.mod.failNode(scope, node, "TODO implement int literals that don't fit in a u64", .{});4026 },
3814 }4027 .fn_proto_one => {
3815}4028 var params: [1]ast.Node.Index = undefined;
4029 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
4030 error.OutOfMemory => return error.OutOfMemory,
4031 error.AnalysisFail => {},
4032 };
4033 continue;
4034 },
4035 .fn_proto => {
4036 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
4037 error.OutOfMemory => return error.OutOfMemory,
4038 error.AnalysisFail => {},
4039 };
4040 continue;
4041 },
4042 else => unreachable,
4043 }
4044 },
4045 .fn_proto_simple => {
4046 var params: [1]ast.Node.Index = undefined;
4047 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
4048 error.OutOfMemory => return error.OutOfMemory,
4049 error.AnalysisFail => {},
4050 };
4051 continue;
4052 },
4053 .fn_proto_multi => {
4054 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
4055 error.OutOfMemory => return error.OutOfMemory,
4056 error.AnalysisFail => {},
4057 };
4058 continue;
4059 },
4060 .fn_proto_one => {
4061 var params: [1]ast.Node.Index = undefined;
4062 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
4063 error.OutOfMemory => return error.OutOfMemory,
4064 error.AnalysisFail => {},
4065 };
4066 continue;
4067 },
4068 .fn_proto => {
4069 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
4070 error.OutOfMemory => return error.OutOfMemory,
4071 error.AnalysisFail => {},
4072 };
4073 continue;
4074 },
38164075
3817fn floatLiteral(4076 .global_var_decl => {
3818 gz: *GenZir,4077 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
3819 scope: *Scope,4078 error.OutOfMemory => return error.OutOfMemory,
3820 rl: ResultLoc,4079 error.AnalysisFail => {},
3821 node: ast.Node.Index,4080 };
3822) InnerError!zir.Inst.Ref {4081 continue;
3823 const arena = gz.astgen.arena;4082 },
3824 const tree = gz.tree();4083 .local_var_decl => {
3825 const main_tokens = tree.nodes.items(.main_token);4084 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
38264085 error.OutOfMemory => return error.OutOfMemory,
3827 const main_token = main_tokens[node];4086 error.AnalysisFail => {},
3828 const bytes = tree.tokenSlice(main_token);4087 };
3829 if (bytes.len > 2 and bytes[1] == 'x') {4088 continue;
3830 assert(bytes[0] == '0'); // validated by tokenizer4089 },
3831 return gz.astgen.mod.failTok(scope, main_token, "TODO implement hex floats", .{});4090 .simple_var_decl => {
3832 }4091 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
3833 const float_number = std.fmt.parseFloat(f128, bytes) catch |e| switch (e) {4092 error.OutOfMemory => return error.OutOfMemory,
3834 error.InvalidCharacter => unreachable, // validated by tokenizer4093 error.AnalysisFail => {},
3835 };4094 };
3836 // If the value fits into a f32 without losing any precision, store it that way.4095 continue;
3837 @setFloatMode(.Strict);4096 },
3838 const smaller_float = @floatCast(f32, float_number);4097 .aligned_var_decl => {
3839 const bigger_again: f128 = smaller_float;4098 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
3840 if (bigger_again == float_number) {4099 error.OutOfMemory => return error.OutOfMemory,
3841 const result = try gz.addFloat(smaller_float, node);4100 error.AnalysisFail => {},
3842 return rvalue(gz, scope, rl, result, node);4101 };
3843 }4102 continue;
3844 // We need to use 128 bits. Break the float into 4 u32 values so we can4103 },
3845 // put it into the `extra` array.
3846 const int_bits = @bitCast(u128, float_number);
3847 const result = try gz.addPlNode(.float128, node, zir.Inst.Float128{
3848 .piece0 = @truncate(u32, int_bits),
3849 .piece1 = @truncate(u32, int_bits >> 32),
3850 .piece2 = @truncate(u32, int_bits >> 64),
3851 .piece3 = @truncate(u32, int_bits >> 96),
3852 });
3853 return rvalue(gz, scope, rl, result, node);
3854}
38554104
3856fn asmExpr(4105 .@"comptime" => {
3857 gz: *GenZir,4106 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3858 scope: *Scope,4107 error.OutOfMemory => return error.OutOfMemory,
3859 rl: ResultLoc,4108 error.AnalysisFail => {},
3860 node: ast.Node.Index,4109 };
3861 full: ast.full.Asm,4110 continue;
3862) InnerError!zir.Inst.Ref {4111 },
3863 const mod = gz.astgen.mod;4112 .@"usingnamespace" => {
3864 const arena = gz.astgen.arena;4113 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3865 const tree = gz.tree();4114 error.OutOfMemory => return error.OutOfMemory,
3866 const main_tokens = tree.nodes.items(.main_token);4115 error.AnalysisFail => {},
3867 const node_datas = tree.nodes.items(.data);4116 };
4117 continue;
4118 },
4119 .test_decl => {
4120 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
4121 error.OutOfMemory => return error.OutOfMemory,
4122 error.AnalysisFail => {},
4123 };
4124 continue;
4125 },
4126 else => unreachable,
4127 };
4128 if (field_index % 32 == 0 and field_index != 0) {
4129 try bit_bag.append(gpa, cur_bit_bag);
4130 cur_bit_bag = 0;
4131 }
4132 assert(member.comptime_token == null);
4133 assert(member.ast.type_expr == 0);
4134 assert(member.ast.align_expr == 0);
38684135
3869 const asm_source = try expr(gz, scope, .{ .ty = .const_slice_u8_type }, full.ast.template);4136 const field_name = try astgen.identAsString(member.ast.name_token);
4137 fields_data.appendAssumeCapacity(field_name);
38704138
3871 if (full.outputs.len != 0) {4139 const have_value = member.ast.value_expr != 0;
3872 // when implementing this be sure to add test coverage for the asm return type4140 cur_bit_bag = (cur_bit_bag >> 1) |
3873 // not resolving into a type (the node_offset_asm_ret_ty field of LazySrcLoc)4141 (@as(u32, @boolToInt(have_value)) << 31);
3874 return mod.failTok(scope, full.ast.asm_token, "TODO implement asm with an output", .{});
3875 }
38764142
3877 const constraints = try arena.alloc(u32, full.inputs.len);4143 if (have_value) {
3878 const args = try arena.alloc(zir.Inst.Ref, full.inputs.len);4144 if (arg_inst == .none) {
4145 return astgen.failNodeNotes(
4146 node,
4147 "explicitly valued enum missing integer tag type",
4148 .{},
4149 &[_]u32{
4150 try astgen.errNoteNode(
4151 member.ast.value_expr,
4152 "tag value specified here",
4153 .{},
4154 ),
4155 },
4156 );
4157 }
4158 const tag_value_inst = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr);
4159 fields_data.appendAssumeCapacity(@enumToInt(tag_value_inst));
4160 }
38794161
3880 for (full.inputs) |input, i| {4162 field_index += 1;
3881 const constraint_token = main_tokens[input] + 2;4163 }
3882 const string_bytes = &gz.astgen.string_bytes;4164 {
3883 constraints[i] = @intCast(u32, string_bytes.items.len);4165 const empty_slot_count = 32 - (field_index % 32);
3884 const token_bytes = tree.tokenSlice(constraint_token);4166 if (empty_slot_count < 32) {
3885 try mod.parseStrLit(scope, constraint_token, string_bytes, token_bytes, 0);4167 cur_bit_bag >>= @intCast(u5, empty_slot_count);
3886 try string_bytes.append(mod.gpa, 0);4168 }
4169 }
4170 {
4171 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
4172 if (empty_slot_count < WipDecls.fields_per_u32) {
4173 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
4174 }
4175 }
38874176
3888 args[i] = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[input].lhs);4177 const decl_inst = try gz.reserveInstructionIndex();
3889 }4178 if (block_scope.instructions.items.len != 0) {
4179 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
4180 }
38904181
3891 const tag: zir.Inst.Tag = if (full.volatile_token != null) .asm_volatile else .@"asm";4182 try gz.setEnum(decl_inst, .{
3892 const result = try gz.addPlNode(tag, node, zir.Inst.Asm{4183 .src_node = node,
3893 .asm_source = asm_source,4184 .nonexhaustive = nonexhaustive,
3894 .return_type = .void_type,4185 .tag_type = arg_inst,
3895 .output = .none,4186 .body_len = @intCast(u32, block_scope.instructions.items.len),
3896 .args_len = @intCast(u32, full.inputs.len),4187 .fields_len = @intCast(u32, field_index),
3897 .clobbers_len = 0, // TODO implement asm clobbers4188 .decls_len = @intCast(u32, wip_decls.decl_index),
3898 });4189 });
38994190
3900 try gz.astgen.extra.ensureCapacity(mod.gpa, gz.astgen.extra.items.len +4191 try astgen.extra.ensureUnusedCapacity(gpa, bit_bag.items.len +
3901 args.len + constraints.len);4192 1 + fields_data.items.len +
3902 gz.astgen.appendRefsAssumeCapacity(args);4193 block_scope.instructions.items.len +
3903 gz.astgen.extra.appendSliceAssumeCapacity(constraints);4194 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
4195 wip_decls.payload.items.len);
4196 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
4197 if (wip_decls.decl_index != 0) {
4198 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
4199 }
4200 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
39044201
3905 return rvalue(gz, scope, rl, result, node);4202 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
3906}4203 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
4204 astgen.extra.appendAssumeCapacity(cur_bit_bag);
4205 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
39074206
3908fn as(4207 return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node);
3909 gz: *GenZir,
3910 scope: *Scope,
3911 rl: ResultLoc,
3912 node: ast.Node.Index,
3913 lhs: ast.Node.Index,
3914 rhs: ast.Node.Index,
3915) InnerError!zir.Inst.Ref {
3916 const dest_type = try typeExpr(gz, scope, lhs);
3917 switch (rl) {
3918 .none, .none_or_ref, .discard, .ref, .ty => {
3919 const result = try expr(gz, scope, .{ .ty = dest_type }, rhs);
3920 return rvalue(gz, scope, rl, result, node);
3921 },4208 },
4209 .keyword_opaque => {
4210 var namespace: Scope.Namespace = .{ .parent = &gz.base };
4211 defer namespace.decls.deinit(gpa);
39224212
3923 .ptr => |result_ptr| {4213 var wip_decls: WipDecls = .{};
3924 return asRlPtr(gz, scope, rl, result_ptr, rhs, dest_type);4214 defer wip_decls.deinit(gpa);
3925 },
3926 .block_ptr => |block_scope| {
3927 return asRlPtr(gz, scope, rl, block_scope.rl_ptr, rhs, dest_type);
3928 },
39294215
3930 .inferred_ptr => |result_alloc| {4216 for (container_decl.ast.members) |member_node| {
3931 // TODO here we should be able to resolve the inference; we now have a type for the result.4217 const member = switch (node_tags[member_node]) {
3932 return gz.astgen.mod.failNode(scope, node, "TODO implement @as with inferred-type result location pointer", .{});4218 .container_field_init => tree.containerFieldInit(member_node),
3933 },4219 .container_field_align => tree.containerFieldAlign(member_node),
3934 }4220 .container_field => tree.containerField(member_node),
3935}
39364221
3937fn asRlPtr(4222 .fn_decl => {
3938 parent_gz: *GenZir,4223 const fn_proto = node_datas[member_node].lhs;
3939 scope: *Scope,4224 const body = node_datas[member_node].rhs;
3940 rl: ResultLoc,4225 switch (node_tags[fn_proto]) {
3941 result_ptr: zir.Inst.Ref,4226 .fn_proto_simple => {
3942 operand_node: ast.Node.Index,4227 var params: [1]ast.Node.Index = undefined;
3943 dest_type: zir.Inst.Ref,4228 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
3944) InnerError!zir.Inst.Ref {4229 error.OutOfMemory => return error.OutOfMemory,
3945 // Detect whether this expr() call goes into rvalue() to store the result into the4230 error.AnalysisFail => {},
3946 // result location. If it does, elide the coerce_result_ptr instruction4231 };
3947 // as well as the store instruction, instead passing the result as an rvalue.4232 continue;
3948 const astgen = parent_gz.astgen;4233 },
4234 .fn_proto_multi => {
4235 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
4236 error.OutOfMemory => return error.OutOfMemory,
4237 error.AnalysisFail => {},
4238 };
4239 continue;
4240 },
4241 .fn_proto_one => {
4242 var params: [1]ast.Node.Index = undefined;
4243 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
4244 error.OutOfMemory => return error.OutOfMemory,
4245 error.AnalysisFail => {},
4246 };
4247 continue;
4248 },
4249 .fn_proto => {
4250 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
4251 error.OutOfMemory => return error.OutOfMemory,
4252 error.AnalysisFail => {},
4253 };
4254 continue;
4255 },
4256 else => unreachable,
4257 }
4258 },
4259 .fn_proto_simple => {
4260 var params: [1]ast.Node.Index = undefined;
4261 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
4262 error.OutOfMemory => return error.OutOfMemory,
4263 error.AnalysisFail => {},
4264 };
4265 continue;
4266 },
4267 .fn_proto_multi => {
4268 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
4269 error.OutOfMemory => return error.OutOfMemory,
4270 error.AnalysisFail => {},
4271 };
4272 continue;
4273 },
4274 .fn_proto_one => {
4275 var params: [1]ast.Node.Index = undefined;
4276 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
4277 error.OutOfMemory => return error.OutOfMemory,
4278 error.AnalysisFail => {},
4279 };
4280 continue;
4281 },
4282 .fn_proto => {
4283 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
4284 error.OutOfMemory => return error.OutOfMemory,
4285 error.AnalysisFail => {},
4286 };
4287 continue;
4288 },
39494289
3950 var as_scope: GenZir = .{4290 .global_var_decl => {
3951 .parent = scope,4291 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
3952 .astgen = astgen,4292 error.OutOfMemory => return error.OutOfMemory,
3953 .force_comptime = parent_gz.force_comptime,4293 error.AnalysisFail => {},
3954 .instructions = .{},4294 };
3955 };4295 continue;
3956 defer as_scope.instructions.deinit(astgen.mod.gpa);4296 },
4297 .local_var_decl => {
4298 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
4299 error.OutOfMemory => return error.OutOfMemory,
4300 error.AnalysisFail => {},
4301 };
4302 continue;
4303 },
4304 .simple_var_decl => {
4305 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
4306 error.OutOfMemory => return error.OutOfMemory,
4307 error.AnalysisFail => {},
4308 };
4309 continue;
4310 },
4311 .aligned_var_decl => {
4312 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
4313 error.OutOfMemory => return error.OutOfMemory,
4314 error.AnalysisFail => {},
4315 };
4316 continue;
4317 },
39574318
3958 as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr);4319 .@"comptime" => {
3959 const result = try expr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node);4320 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3960 const parent_zir = &parent_gz.instructions;4321 error.OutOfMemory => return error.OutOfMemory,
3961 if (as_scope.rvalue_rl_count == 1) {4322 error.AnalysisFail => {},
3962 // Busted! This expression didn't actually need a pointer.4323 };
3963 const zir_tags = astgen.instructions.items(.tag);4324 continue;
3964 const zir_datas = astgen.instructions.items(.data);4325 },
3965 const expected_len = parent_zir.items.len + as_scope.instructions.items.len - 2;4326 .@"usingnamespace" => {
3966 try parent_zir.ensureCapacity(astgen.mod.gpa, expected_len);4327 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3967 for (as_scope.instructions.items) |src_inst| {4328 error.OutOfMemory => return error.OutOfMemory,
3968 if (astgen.indexToRef(src_inst) == as_scope.rl_ptr) continue;4329 error.AnalysisFail => {},
3969 if (zir_tags[src_inst] == .store_to_block_ptr) {4330 };
3970 if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue;4331 continue;
4332 },
4333 .test_decl => {
4334 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
4335 error.OutOfMemory => return error.OutOfMemory,
4336 error.AnalysisFail => {},
4337 };
4338 continue;
4339 },
4340 else => unreachable,
4341 };
3971 }4342 }
3972 parent_zir.appendAssumeCapacity(src_inst);4343 {
3973 }4344 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
3974 assert(parent_zir.items.len == expected_len);4345 if (empty_slot_count < WipDecls.fields_per_u32) {
3975 const casted_result = try parent_gz.addBin(.as, dest_type, result);4346 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
3976 return rvalue(parent_gz, scope, rl, casted_result, operand_node);4347 }
3977 } else {4348 }
3978 try parent_zir.appendSlice(astgen.mod.gpa, as_scope.instructions.items);4349 const tag: Zir.Inst.Tag = switch (gz.anon_name_strategy) {
3979 return result;4350 .parent => .opaque_decl,
3980 }4351 .anon => .opaque_decl_anon,
3981}4352 .func => .opaque_decl_func,
4353 };
4354 const decl_inst = try gz.addBlock(tag, node);
4355 try gz.instructions.append(gpa, decl_inst);
39824356
3983fn bitCast(4357 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len +
3984 gz: *GenZir,4358 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
3985 scope: *Scope,4359 wip_decls.payload.items.len);
3986 rl: ResultLoc,4360 const zir_datas = astgen.instructions.items(.data);
3987 node: ast.Node.Index,4361 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{
3988 lhs: ast.Node.Index,4362 .decls_len = @intCast(u32, wip_decls.decl_index),
3989 rhs: ast.Node.Index,
3990) InnerError!zir.Inst.Ref {
3991 const mod = gz.astgen.mod;
3992 const dest_type = try typeExpr(gz, scope, lhs);
3993 switch (rl) {
3994 .none, .discard, .ty => {
3995 const operand = try expr(gz, scope, .none, rhs);
3996 const result = try gz.addPlNode(.bitcast, node, zir.Inst.Bin{
3997 .lhs = dest_type,
3998 .rhs = operand,
3999 });4363 });
4000 return rvalue(gz, scope, rl, result, node);4364 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
4001 },4365 if (wip_decls.decl_index != 0) {
4002 .ref, .none_or_ref => unreachable, // `@bitCast` is not allowed as an r-value.4366 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
4003 .ptr => |result_ptr| {4367 }
4004 const casted_result_ptr = try gz.addUnNode(.bitcast_result_ptr, result_ptr, node);4368 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
4005 return expr(gz, scope, .{ .ptr = casted_result_ptr }, rhs);4369
4006 },4370 return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node);
4007 .block_ptr => |block_ptr| {
4008 return mod.failNode(scope, node, "TODO implement @bitCast with result location inferred peer types", .{});
4009 },
4010 .inferred_ptr => |result_alloc| {
4011 // TODO here we should be able to resolve the inference; we now have a type for the result.
4012 return mod.failNode(scope, node, "TODO implement @bitCast with inferred-type result location pointer", .{});
4013 },4371 },
4372 else => unreachable,
4014 }4373 }
4015}4374}
40164375
4017fn typeOf(4376fn errorSetDecl(
4018 gz: *GenZir,4377 gz: *GenZir,
4019 scope: *Scope,4378 scope: *Scope,
4020 rl: ResultLoc,4379 rl: ResultLoc,
4021 node: ast.Node.Index,4380 node: ast.Node.Index,
4022 params: []const ast.Node.Index,4381) InnerError!Zir.Inst.Ref {
4023) InnerError!zir.Inst.Ref {4382 const astgen = gz.astgen;
4024 if (params.len < 1) {4383 const gpa = astgen.gpa;
4025 return gz.astgen.mod.failNode(scope, node, "expected at least 1 argument, found 0", .{});4384 const tree = astgen.tree;
4026 }4385 const main_tokens = tree.nodes.items(.main_token);
4027 if (params.len == 1) {4386 const token_tags = tree.tokens.items(.tag);
4028 const result = try gz.addUnNode(.typeof, try expr(gz, scope, .none, params[0]), node);4387
4029 return rvalue(gz, scope, rl, result, node);4388 var field_names: std.ArrayListUnmanaged(u32) = .{};
4030 }4389 defer field_names.deinit(gpa);
4031 const arena = gz.astgen.arena;4390
4032 var items = try arena.alloc(zir.Inst.Ref, params.len);4391 {
4033 for (params) |param, param_i| {4392 const error_token = main_tokens[node];
4034 items[param_i] = try expr(gz, scope, .none, param);4393 var tok_i = error_token + 2;
4394 var field_i: usize = 0;
4395 while (true) : (tok_i += 1) {
4396 switch (token_tags[tok_i]) {
4397 .doc_comment, .comma => {},
4398 .identifier => {
4399 const str_index = try astgen.identAsString(tok_i);
4400 try field_names.append(gpa, str_index);
4401 field_i += 1;
4402 },
4403 .r_brace => break,
4404 else => unreachable,
4405 }
4406 }
4035 }4407 }
40364408
4037 const result = try gz.addPlNode(.typeof_peer, node, zir.Inst.MultiOp{4409 const tag: Zir.Inst.Tag = switch (gz.anon_name_strategy) {
4038 .operands_len = @intCast(u32, params.len),4410 .parent => .error_set_decl,
4411 .anon => .error_set_decl_anon,
4412 .func => .error_set_decl_func,
4413 };
4414 const result = try gz.addPlNode(.error_set_decl, node, Zir.Inst.ErrorSetDecl{
4415 .fields_len = @intCast(u32, field_names.items.len),
4039 });4416 });
4040 try gz.astgen.appendRefs(items);4417 try astgen.extra.appendSlice(gpa, field_names.items);
4041
4042 return rvalue(gz, scope, rl, result, node);4418 return rvalue(gz, scope, rl, result, node);
4043}4419}
40444420
4045fn builtinCall(4421fn tryExpr(
4046 gz: *GenZir,4422 parent_gz: *GenZir,
4047 scope: *Scope,4423 scope: *Scope,
4048 rl: ResultLoc,4424 rl: ResultLoc,
4049 node: ast.Node.Index,4425 node: ast.Node.Index,
4050 params: []const ast.Node.Index,4426 operand_node: ast.Node.Index,
4051) InnerError!zir.Inst.Ref {4427) InnerError!Zir.Inst.Ref {
4052 const mod = gz.astgen.mod;4428 const astgen = parent_gz.astgen;
4053 const tree = gz.tree();4429 const tree = astgen.tree;
4054 const main_tokens = tree.nodes.items(.main_token);
40554430
4056 const builtin_token = main_tokens[node];4431 const fn_block = astgen.fn_block orelse {
4057 const builtin_name = tree.tokenSlice(builtin_token);4432 return astgen.failNode(node, "invalid 'try' outside function scope", .{});
4433 };
40584434
4059 // We handle the different builtins manually because they have different semantics depending4435 var block_scope = parent_gz.makeSubBlock(scope);
4060 // on the function. For example, `@as` and others participate in result location semantics,4436 block_scope.setBreakResultLoc(rl);
4061 // and `@cImport` creates a special scope that collects a .c source code text buffer.4437 defer block_scope.instructions.deinit(astgen.gpa);
4062 // Also, some builtins have a variable number of parameters.
40634438
4064 const info = BuiltinFn.list.get(builtin_name) orelse {4439 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {
4065 return mod.failNode(scope, node, "invalid builtin function: '{s}'", .{4440 .ref => .ref,
4066 builtin_name,4441 else => .none,
4067 });
4068 };4442 };
4069 if (info.param_count) |expected| {4443 const err_ops = switch (rl) {
4070 if (expected != params.len) {4444 // zig fmt: off
4071 const s = if (expected == 1) "" else "s";4445 .ref => [3]Zir.Inst.Tag{ .is_err_ptr, .err_union_code_ptr, .err_union_payload_unsafe_ptr },
4072 return mod.failNode(scope, node, "expected {d} parameter{s}, found {d}", .{4446 else => [3]Zir.Inst.Tag{ .is_err, .err_union_code, .err_union_payload_unsafe },
4073 expected, s, params.len,4447 // zig fmt: on
4074 });4448 };
4075 }4449 // This could be a pointer or value depending on the `operand_rl` parameter.
4076 }4450 // We cannot use `block_scope.break_result_loc` because that has the bare
40774451 // type, whereas this expression has the optional type. Later we make
4078 switch (info.tag) {4452 // up for this fact by calling rvalue on the else branch.
4079 .ptr_to_int => {4453 const operand = try expr(&block_scope, &block_scope.base, operand_rl, operand_node);
4080 const operand = try expr(gz, scope, .none, params[0]);4454 const cond = try block_scope.addUnNode(err_ops[0], operand, node);
4081 const result = try gz.addUnNode(.ptrtoint, operand, node);4455 const condbr = try block_scope.addCondBr(.condbr, node);
4082 return rvalue(gz, scope, rl, result, node);
4083 },
4084 .float_cast => {
4085 const dest_type = try typeExpr(gz, scope, params[0]);
4086 const rhs = try expr(gz, scope, .none, params[1]);
4087 const result = try gz.addPlNode(.floatcast, node, zir.Inst.Bin{
4088 .lhs = dest_type,
4089 .rhs = rhs,
4090 });
4091 return rvalue(gz, scope, rl, result, node);
4092 },
4093 .int_cast => {
4094 const dest_type = try typeExpr(gz, scope, params[0]);
4095 const rhs = try expr(gz, scope, .none, params[1]);
4096 const result = try gz.addPlNode(.intcast, node, zir.Inst.Bin{
4097 .lhs = dest_type,
4098 .rhs = rhs,
4099 });
4100 return rvalue(gz, scope, rl, result, node);
4101 },
4102 .breakpoint => {
4103 _ = try gz.add(.{
4104 .tag = .breakpoint,
4105 .data = .{ .node = gz.astgen.decl.nodeIndexToRelative(node) },
4106 });
4107 return rvalue(gz, scope, rl, .void_value, node);
4108 },
4109 .import => {
4110 const target = try expr(gz, scope, .none, params[0]);
4111 const result = try gz.addUnNode(.import, target, node);
4112 return rvalue(gz, scope, rl, result, node);
4113 },
4114 .error_to_int => {
4115 const target = try expr(gz, scope, .none, params[0]);
4116 const result = try gz.addUnNode(.error_to_int, target, node);
4117 return rvalue(gz, scope, rl, result, node);
4118 },
4119 .int_to_error => {
4120 const target = try expr(gz, scope, .{ .ty = .u16_type }, params[0]);
4121 const result = try gz.addUnNode(.int_to_error, target, node);
4122 return rvalue(gz, scope, rl, result, node);
4123 },
4124 .compile_error => {
4125 const target = try expr(gz, scope, .none, params[0]);
4126 const result = try gz.addUnNode(.compile_error, target, node);
4127 return rvalue(gz, scope, rl, result, node);
4128 },
4129 .set_eval_branch_quota => {
4130 const quota = try expr(gz, scope, .{ .ty = .u32_type }, params[0]);
4131 const result = try gz.addUnNode(.set_eval_branch_quota, quota, node);
4132 return rvalue(gz, scope, rl, result, node);
4133 },
4134 .compile_log => {
4135 const arg_refs = try mod.gpa.alloc(zir.Inst.Ref, params.len);
4136 defer mod.gpa.free(arg_refs);
4137
4138 for (params) |param, i| arg_refs[i] = try expr(gz, scope, .none, param);
4139
4140 const result = try gz.addPlNode(.compile_log, node, zir.Inst.MultiOp{
4141 .operands_len = @intCast(u32, params.len),
4142 });
4143 try gz.astgen.appendRefs(arg_refs);
4144 return rvalue(gz, scope, rl, result, node);
4145 },
4146 .field => {
4147 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
4148 if (rl == .ref) {
4149 return try gz.addPlNode(.field_ptr_named, node, zir.Inst.FieldNamed{
4150 .lhs = try expr(gz, scope, .ref, params[0]),
4151 .field_name = field_name,
4152 });
4153 }
4154 const result = try gz.addPlNode(.field_val_named, node, zir.Inst.FieldNamed{
4155 .lhs = try expr(gz, scope, .none, params[0]),
4156 .field_name = field_name,
4157 });
4158 return rvalue(gz, scope, rl, result, node);
4159 },
4160 .as => return as(gz, scope, rl, node, params[0], params[1]),
4161 .bit_cast => return bitCast(gz, scope, rl, node, params[0], params[1]),
4162 .TypeOf => return typeOf(gz, scope, rl, node, params),
4163
4164 .int_to_enum => {
4165 const result = try gz.addPlNode(.int_to_enum, node, zir.Inst.Bin{
4166 .lhs = try typeExpr(gz, scope, params[0]),
4167 .rhs = try expr(gz, scope, .none, params[1]),
4168 });
4169 return rvalue(gz, scope, rl, result, node);
4170 },
41714456
4172 .enum_to_int => {4457 const block = try parent_gz.addBlock(.block, node);
4173 const operand = try expr(gz, scope, .none, params[0]);4458 try parent_gz.instructions.append(astgen.gpa, block);
4174 const result = try gz.addUnNode(.enum_to_int, operand, node);4459 try block_scope.setBlockBody(block);
4175 return rvalue(gz, scope, rl, result, node);
4176 },
41774460
4178 .@"export" => {4461 var then_scope = parent_gz.makeSubBlock(scope);
4179 // TODO: @export is supposed to be able to export things other than functions.4462 defer then_scope.instructions.deinit(astgen.gpa);
4180 // Instead of `comptimeExpr` here we need `decl_ref`.
4181 const fn_to_export = try comptimeExpr(gz, scope, .none, params[0]);
4182 // TODO: the second parameter here is supposed to be
4183 // `std.builtin.ExportOptions`, not a string.
4184 const export_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
4185 _ = try gz.addPlNode(.@"export", node, zir.Inst.Bin{
4186 .lhs = fn_to_export,
4187 .rhs = export_name,
4188 });
4189 return rvalue(gz, scope, rl, .void_value, node);
4190 },
41914463
4192 .has_decl => {4464 const err_code = try then_scope.addUnNode(err_ops[1], operand, node);
4193 const container_type = try typeExpr(gz, scope, params[0]);4465 try genDefers(&then_scope, &fn_block.base, scope, err_code);
4194 const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);4466 const then_result = try then_scope.addUnNode(.ret_node, err_code, node);
4195 const result = try gz.addPlNode(.has_decl, node, zir.Inst.Bin{
4196 .lhs = container_type,
4197 .rhs = name,
4198 });
4199 return rvalue(gz, scope, rl, result, node);
4200 },
42014467
4202 .type_info => {4468 var else_scope = parent_gz.makeSubBlock(scope);
4203 const operand = try typeExpr(gz, scope, params[0]);4469 defer else_scope.instructions.deinit(astgen.gpa);
4204 const result = try gz.addUnNode(.type_info, operand, node);
4205 return rvalue(gz, scope, rl, result, node);
4206 },
42074470
4208 .add_with_overflow,4471 block_scope.break_count += 1;
4209 .align_cast,4472 // This could be a pointer or value depending on `err_ops[2]`.
4210 .align_of,4473 const unwrapped_payload = try else_scope.addUnNode(err_ops[2], operand, node);
4211 .atomic_load,4474 const else_result = switch (rl) {
4212 .atomic_rmw,4475 .ref => unwrapped_payload,
4213 .atomic_store,4476 else => try rvalue(&else_scope, &else_scope.base, block_scope.break_result_loc, unwrapped_payload, node),
4214 .bit_offset_of,4477 };
4215 .bool_to_int,
4216 .bit_size_of,
4217 .mul_add,
4218 .byte_swap,
4219 .bit_reverse,
4220 .byte_offset_of,
4221 .call,
4222 .c_define,
4223 .c_import,
4224 .c_include,
4225 .clz,
4226 .cmpxchg_strong,
4227 .cmpxchg_weak,
4228 .ctz,
4229 .c_undef,
4230 .div_exact,
4231 .div_floor,
4232 .div_trunc,
4233 .embed_file,
4234 .error_name,
4235 .error_return_trace,
4236 .err_set_cast,
4237 .fence,
4238 .field_parent_ptr,
4239 .float_to_int,
4240 .has_field,
4241 .int_to_float,
4242 .int_to_ptr,
4243 .memcpy,
4244 .memset,
4245 .wasm_memory_size,
4246 .wasm_memory_grow,
4247 .mod,
4248 .mul_with_overflow,
4249 .panic,
4250 .pop_count,
4251 .ptr_cast,
4252 .rem,
4253 .return_address,
4254 .set_align_stack,
4255 .set_cold,
4256 .set_float_mode,
4257 .set_runtime_safety,
4258 .shl_exact,
4259 .shl_with_overflow,
4260 .shr_exact,
4261 .shuffle,
4262 .size_of,
4263 .splat,
4264 .reduce,
4265 .src,
4266 .sqrt,
4267 .sin,
4268 .cos,
4269 .exp,
4270 .exp2,
4271 .log,
4272 .log2,
4273 .log10,
4274 .fabs,
4275 .floor,
4276 .ceil,
4277 .trunc,
4278 .round,
4279 .sub_with_overflow,
4280 .tag_name,
4281 .This,
4282 .truncate,
4283 .Type,
4284 .type_name,
4285 .union_init,
4286 => return mod.failNode(scope, node, "TODO: implement builtin function {s}", .{
4287 builtin_name,
4288 }),
42894478
4290 .async_call,4479 return finishThenElseBlock(
4291 .frame,4480 parent_gz,
4292 .Frame,4481 scope,
4293 .frame_address,4482 rl,
4294 .frame_size,4483 node,
4295 => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),4484 &block_scope,
4296 }4485 &then_scope,
4486 &else_scope,
4487 condbr,
4488 cond,
4489 node,
4490 node,
4491 then_result,
4492 else_result,
4493 block,
4494 block,
4495 .@"break",
4496 );
4297}4497}
42984498
4299fn callExpr(4499fn orelseCatchExpr(
4300 gz: *GenZir,4500 parent_gz: *GenZir,
4301 scope: *Scope,4501 scope: *Scope,
4302 rl: ResultLoc,4502 rl: ResultLoc,
4303 node: ast.Node.Index,4503 node: ast.Node.Index,
4304 call: ast.full.Call,4504 lhs: ast.Node.Index,
4305) InnerError!zir.Inst.Ref {4505 cond_op: Zir.Inst.Tag,
4306 const mod = gz.astgen.mod;4506 unwrap_op: Zir.Inst.Tag,
4307 if (call.async_token) |async_token| {4507 unwrap_code_op: Zir.Inst.Tag,
4308 return mod.failTok(scope, async_token, "async and related features are not yet supported", .{});4508 rhs: ast.Node.Index,
4309 }4509 payload_token: ?ast.TokenIndex,
4310 const lhs = try expr(gz, scope, .none, call.ast.fn_expr);4510) InnerError!Zir.Inst.Ref {
43114511 const astgen = parent_gz.astgen;
4312 const args = try mod.gpa.alloc(zir.Inst.Ref, call.ast.params.len);4512 const tree = astgen.tree;
4313 defer mod.gpa.free(args);
43144513
4315 for (call.ast.params) |param_node, i| {4514 var block_scope = parent_gz.makeSubBlock(scope);
4316 const param_type = try gz.add(.{4515 block_scope.setBreakResultLoc(rl);
4317 .tag = .param_type,4516 defer block_scope.instructions.deinit(astgen.gpa);
4318 .data = .{ .param_type = .{
4319 .callee = lhs,
4320 .param_index = @intCast(u32, i),
4321 } },
4322 });
4323 args[i] = try expr(gz, scope, .{ .ty = param_type }, param_node);
4324 }
43254517
4326 const modifier: std.builtin.CallOptions.Modifier = switch (call.async_token != null) {4518 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {
4327 true => .async_kw,4519 .ref => .ref,
4328 false => .auto,4520 else => .none,
4329 };4521 };
4330 const result: zir.Inst.Ref = res: {4522 block_scope.break_count += 1;
4331 const tag: zir.Inst.Tag = switch (modifier) {4523 // This could be a pointer or value depending on the `operand_rl` parameter.
4332 .auto => switch (args.len == 0) {4524 // We cannot use `block_scope.break_result_loc` because that has the bare
4333 true => break :res try gz.addUnNode(.call_none, lhs, node),4525 // type, whereas this expression has the optional type. Later we make
4334 false => .call,4526 // up for this fact by calling rvalue on the else branch.
4335 },4527 const operand = try expr(&block_scope, &block_scope.base, operand_rl, lhs);
4336 .async_kw => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),4528 const cond = try block_scope.addUnNode(cond_op, operand, node);
4337 .never_tail => unreachable,4529 const condbr = try block_scope.addCondBr(.condbr, node);
4338 .never_inline => unreachable,4530
4339 .no_async => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),4531 const block = try parent_gz.addBlock(.block, node);
4340 .always_tail => unreachable,4532 try parent_gz.instructions.append(astgen.gpa, block);
4341 .always_inline => unreachable,4533 try block_scope.setBlockBody(block);
4342 .compile_time => .call_compile_time,4534
4535 var then_scope = parent_gz.makeSubBlock(scope);
4536 defer then_scope.instructions.deinit(astgen.gpa);
4537
4538 var err_val_scope: Scope.LocalVal = undefined;
4539 const then_sub_scope = blk: {
4540 const payload = payload_token orelse break :blk &then_scope.base;
4541 if (mem.eql(u8, tree.tokenSlice(payload), "_")) {
4542 return astgen.failTok(payload, "discard of error capture; omit it instead", .{});
4543 }
4544 const err_name = try astgen.identAsString(payload);
4545 err_val_scope = .{
4546 .parent = &then_scope.base,
4547 .gen_zir = &then_scope,
4548 .name = err_name,
4549 .inst = try then_scope.addUnNode(unwrap_code_op, operand, node),
4550 .token_src = payload,
4343 };4551 };
4344 break :res try gz.addCall(tag, lhs, args, node);4552 break :blk &err_val_scope.base;
4345 };4553 };
4346 return rvalue(gz, scope, rl, result, node); // TODO function call with result location
4347}
43484554
4349pub const simple_types = std.ComptimeStringMap(zir.Inst.Ref, .{4555 block_scope.break_count += 1;
4350 .{ "u8", .u8_type },4556 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, rhs);
4351 .{ "i8", .i8_type },4557 // We hold off on the break instructions as well as copying the then/else
4352 .{ "u16", .u16_type },4558 // instructions into place until we know whether to keep store_to_block_ptr
4353 .{ "i16", .i16_type },4559 // instructions or not.
4354 .{ "u32", .u32_type },
4355 .{ "i32", .i32_type },
4356 .{ "u64", .u64_type },
4357 .{ "i64", .i64_type },
4358 .{ "usize", .usize_type },
4359 .{ "isize", .isize_type },
4360 .{ "c_short", .c_short_type },
4361 .{ "c_ushort", .c_ushort_type },
4362 .{ "c_int", .c_int_type },
4363 .{ "c_uint", .c_uint_type },
4364 .{ "c_long", .c_long_type },
4365 .{ "c_ulong", .c_ulong_type },
4366 .{ "c_longlong", .c_longlong_type },
4367 .{ "c_ulonglong", .c_ulonglong_type },
4368 .{ "c_longdouble", .c_longdouble_type },
4369 .{ "f16", .f16_type },
4370 .{ "f32", .f32_type },
4371 .{ "f64", .f64_type },
4372 .{ "f128", .f128_type },
4373 .{ "c_void", .c_void_type },
4374 .{ "bool", .bool_type },
4375 .{ "void", .void_type },
4376 .{ "type", .type_type },
4377 .{ "anyerror", .anyerror_type },
4378 .{ "comptime_int", .comptime_int_type },
4379 .{ "comptime_float", .comptime_float_type },
4380 .{ "noreturn", .noreturn_type },
4381 .{ "null", .null_type },
4382 .{ "undefined", .undefined_type },
4383 .{ "undefined", .undef },
4384 .{ "null", .null_value },
4385 .{ "true", .bool_true },
4386 .{ "false", .bool_false },
4387});
43884560
4389fn nodeMayNeedMemoryLocation(tree: *const ast.Tree, start_node: ast.Node.Index) bool {4561 var else_scope = parent_gz.makeSubBlock(scope);
4390 const node_tags = tree.nodes.items(.tag);4562 defer else_scope.instructions.deinit(astgen.gpa);
4391 const node_datas = tree.nodes.items(.data);
4392 const main_tokens = tree.nodes.items(.main_token);
4393 const token_tags = tree.tokens.items(.tag);
43944563
4395 var node = start_node;4564 // This could be a pointer or value depending on `unwrap_op`.
4396 while (true) {4565 const unwrapped_payload = try else_scope.addUnNode(unwrap_op, operand, node);
4397 switch (node_tags[node]) {4566 const else_result = switch (rl) {
4398 .root,4567 .ref => unwrapped_payload,
4399 .@"usingnamespace",4568 else => try rvalue(&else_scope, &else_scope.base, block_scope.break_result_loc, unwrapped_payload, node),
4400 .test_decl,4569 };
4401 .switch_case,
4402 .switch_case_one,
4403 .container_field_init,
4404 .container_field_align,
4405 .container_field,
4406 .asm_output,
4407 .asm_input,
4408 => unreachable,
44094570
4410 .@"return",4571 return finishThenElseBlock(
4411 .@"break",4572 parent_gz,
4412 .@"continue",4573 scope,
4413 .bit_not,4574 rl,
4414 .bool_not,4575 node,
4415 .global_var_decl,4576 &block_scope,
4416 .local_var_decl,4577 &then_scope,
4417 .simple_var_decl,4578 &else_scope,
4418 .aligned_var_decl,4579 condbr,
4419 .@"defer",4580 cond,
4420 .@"errdefer",4581 node,
4421 .address_of,4582 node,
4422 .optional_type,4583 then_result,
4423 .negation,4584 else_result,
4424 .negation_wrap,4585 block,
4425 .@"resume",4586 block,
4426 .array_type,4587 .@"break",
4427 .array_type_sentinel,4588 );
4428 .ptr_type_aligned,4589}
4429 .ptr_type_sentinel,4590
4430 .ptr_type,4591fn finishThenElseBlock(
4431 .ptr_type_bit_range,4592 parent_gz: *GenZir,
4432 .@"suspend",4593 parent_scope: *Scope,
4433 .@"anytype",4594 rl: ResultLoc,
4434 .fn_proto_simple,4595 node: ast.Node.Index,
4435 .fn_proto_multi,4596 block_scope: *GenZir,
4436 .fn_proto_one,4597 then_scope: *GenZir,
4437 .fn_proto,4598 else_scope: *GenZir,
4438 .fn_decl,4599 condbr: Zir.Inst.Index,
4439 .anyframe_type,4600 cond: Zir.Inst.Ref,
4601 then_src: ast.Node.Index,
4602 else_src: ast.Node.Index,
4603 then_result: Zir.Inst.Ref,
4604 else_result: Zir.Inst.Ref,
4605 main_block: Zir.Inst.Index,
4606 then_break_block: Zir.Inst.Index,
4607 break_tag: Zir.Inst.Tag,
4608) InnerError!Zir.Inst.Ref {
4609 // We now have enough information to decide whether the result instruction should
4610 // be communicated via result location pointer or break instructions.
4611 const strat = rl.strategy(block_scope);
4612 const astgen = block_scope.astgen;
4613 switch (strat.tag) {
4614 .break_void => {
4615 if (!parent_gz.refIsNoReturn(then_result)) {
4616 _ = try then_scope.addBreak(break_tag, then_break_block, .void_value);
4617 }
4618 const elide_else = if (else_result != .none) parent_gz.refIsNoReturn(else_result) else false;
4619 if (!elide_else) {
4620 _ = try else_scope.addBreak(break_tag, main_block, .void_value);
4621 }
4622 assert(!strat.elide_store_to_block_ptr_instructions);
4623 try setCondBrPayload(condbr, cond, then_scope, else_scope);
4624 return parent_gz.indexToRef(main_block);
4625 },
4626 .break_operand => {
4627 if (!parent_gz.refIsNoReturn(then_result)) {
4628 _ = try then_scope.addBreak(break_tag, then_break_block, then_result);
4629 }
4630 if (else_result != .none) {
4631 if (!parent_gz.refIsNoReturn(else_result)) {
4632 _ = try else_scope.addBreak(break_tag, main_block, else_result);
4633 }
4634 } else {
4635 _ = try else_scope.addBreak(break_tag, main_block, .void_value);
4636 }
4637 if (strat.elide_store_to_block_ptr_instructions) {
4638 try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope, block_scope.rl_ptr);
4639 } else {
4640 try setCondBrPayload(condbr, cond, then_scope, else_scope);
4641 }
4642 const block_ref = parent_gz.indexToRef(main_block);
4643 switch (rl) {
4644 .ref => return block_ref,
4645 else => return rvalue(parent_gz, parent_scope, rl, block_ref, node),
4646 }
4647 },
4648 }
4649}
4650
4651/// Return whether the identifier names of two tokens are equal. Resolves @""
4652/// tokens without allocating.
4653/// OK in theory it could do it without allocating. This implementation
4654/// allocates when the @"" form is used.
4655fn tokenIdentEql(astgen: *AstGen, token1: ast.TokenIndex, token2: ast.TokenIndex) !bool {
4656 const ident_name_1 = try astgen.identifierTokenString(token1);
4657 const ident_name_2 = try astgen.identifierTokenString(token2);
4658 return mem.eql(u8, ident_name_1, ident_name_2);
4659}
4660
4661fn fieldAccess(
4662 gz: *GenZir,
4663 scope: *Scope,
4664 rl: ResultLoc,
4665 node: ast.Node.Index,
4666) InnerError!Zir.Inst.Ref {
4667 const astgen = gz.astgen;
4668 const tree = astgen.tree;
4669 const main_tokens = tree.nodes.items(.main_token);
4670 const node_datas = tree.nodes.items(.data);
4671
4672 const object_node = node_datas[node].lhs;
4673 const dot_token = main_tokens[node];
4674 const field_ident = dot_token + 1;
4675 const str_index = try astgen.identAsString(field_ident);
4676 switch (rl) {
4677 .ref => return gz.addPlNode(.field_ptr, node, Zir.Inst.Field{
4678 .lhs = try expr(gz, scope, .ref, object_node),
4679 .field_name_start = str_index,
4680 }),
4681 else => return rvalue(gz, scope, rl, try gz.addPlNode(.field_val, node, Zir.Inst.Field{
4682 .lhs = try expr(gz, scope, .none_or_ref, object_node),
4683 .field_name_start = str_index,
4684 }), node),
4685 }
4686}
4687
4688fn arrayAccess(
4689 gz: *GenZir,
4690 scope: *Scope,
4691 rl: ResultLoc,
4692 node: ast.Node.Index,
4693) InnerError!Zir.Inst.Ref {
4694 const astgen = gz.astgen;
4695 const tree = astgen.tree;
4696 const main_tokens = tree.nodes.items(.main_token);
4697 const node_datas = tree.nodes.items(.data);
4698 switch (rl) {
4699 .ref => return gz.addBin(
4700 .elem_ptr,
4701 try expr(gz, scope, .ref, node_datas[node].lhs),
4702 try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),
4703 ),
4704 else => return rvalue(gz, scope, rl, try gz.addBin(
4705 .elem_val,
4706 try expr(gz, scope, .none_or_ref, node_datas[node].lhs),
4707 try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),
4708 ), node),
4709 }
4710}
4711
4712fn simpleBinOp(
4713 gz: *GenZir,
4714 scope: *Scope,
4715 rl: ResultLoc,
4716 node: ast.Node.Index,
4717 op_inst_tag: Zir.Inst.Tag,
4718) InnerError!Zir.Inst.Ref {
4719 const astgen = gz.astgen;
4720 const tree = astgen.tree;
4721 const node_datas = tree.nodes.items(.data);
4722
4723 const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{
4724 .lhs = try expr(gz, scope, .none, node_datas[node].lhs),
4725 .rhs = try expr(gz, scope, .none, node_datas[node].rhs),
4726 });
4727 return rvalue(gz, scope, rl, result, node);
4728}
4729
4730fn simpleStrTok(
4731 gz: *GenZir,
4732 scope: *Scope,
4733 rl: ResultLoc,
4734 ident_token: ast.TokenIndex,
4735 node: ast.Node.Index,
4736 op_inst_tag: Zir.Inst.Tag,
4737) InnerError!Zir.Inst.Ref {
4738 const astgen = gz.astgen;
4739 const str_index = try astgen.identAsString(ident_token);
4740 const result = try gz.addStrTok(op_inst_tag, str_index, ident_token);
4741 return rvalue(gz, scope, rl, result, node);
4742}
4743
4744fn boolBinOp(
4745 gz: *GenZir,
4746 scope: *Scope,
4747 rl: ResultLoc,
4748 node: ast.Node.Index,
4749 zir_tag: Zir.Inst.Tag,
4750) InnerError!Zir.Inst.Ref {
4751 const astgen = gz.astgen;
4752 const tree = astgen.tree;
4753 const node_datas = tree.nodes.items(.data);
4754
4755 const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs);
4756 const bool_br = try gz.addBoolBr(zir_tag, lhs);
4757
4758 var rhs_scope = gz.makeSubBlock(scope);
4759 defer rhs_scope.instructions.deinit(gz.astgen.gpa);
4760 const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs);
4761 if (!gz.refIsNoReturn(rhs)) {
4762 _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs);
4763 }
4764 try rhs_scope.setBoolBrBody(bool_br);
4765
4766 const block_ref = gz.indexToRef(bool_br);
4767 return rvalue(gz, scope, rl, block_ref, node);
4768}
4769
4770fn ifExpr(
4771 parent_gz: *GenZir,
4772 scope: *Scope,
4773 rl: ResultLoc,
4774 node: ast.Node.Index,
4775 if_full: ast.full.If,
4776) InnerError!Zir.Inst.Ref {
4777 const astgen = parent_gz.astgen;
4778 const tree = astgen.tree;
4779 const token_tags = tree.tokens.items(.tag);
4780
4781 var block_scope = parent_gz.makeSubBlock(scope);
4782 block_scope.setBreakResultLoc(rl);
4783 defer block_scope.instructions.deinit(astgen.gpa);
4784
4785 const payload_is_ref = if (if_full.payload_token) |payload_token|
4786 token_tags[payload_token] == .asterisk
4787 else
4788 false;
4789
4790 const cond: struct {
4791 inst: Zir.Inst.Ref,
4792 bool_bit: Zir.Inst.Ref,
4793 } = c: {
4794 if (if_full.error_token) |error_token| {
4795 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;
4796 const err_union = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr);
4797 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_err_ptr else .is_err;
4798 break :c .{
4799 .inst = err_union,
4800 .bool_bit = try block_scope.addUnNode(tag, err_union, node),
4801 };
4802 } else if (if_full.payload_token) |payload_token| {
4803 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;
4804 const optional = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr);
4805 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;
4806 break :c .{
4807 .inst = optional,
4808 .bool_bit = try block_scope.addUnNode(tag, optional, node),
4809 };
4810 } else {
4811 const cond = try expr(&block_scope, &block_scope.base, bool_rl, if_full.ast.cond_expr);
4812 break :c .{
4813 .inst = cond,
4814 .bool_bit = cond,
4815 };
4816 }
4817 };
4818
4819 const condbr = try block_scope.addCondBr(.condbr, node);
4820
4821 const block = try parent_gz.addBlock(.block, node);
4822 try parent_gz.instructions.append(astgen.gpa, block);
4823 try block_scope.setBlockBody(block);
4824
4825 var then_scope = parent_gz.makeSubBlock(scope);
4826 defer then_scope.instructions.deinit(astgen.gpa);
4827
4828 var payload_val_scope: Scope.LocalVal = undefined;
4829
4830 const then_sub_scope = s: {
4831 if (if_full.error_token) |error_token| {
4832 const tag: Zir.Inst.Tag = if (payload_is_ref)
4833 .err_union_payload_unsafe_ptr
4834 else
4835 .err_union_payload_unsafe;
4836 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
4837 const ident_name = try astgen.identAsString(error_token);
4838 payload_val_scope = .{
4839 .parent = &then_scope.base,
4840 .gen_zir = &then_scope,
4841 .name = ident_name,
4842 .inst = payload_inst,
4843 .token_src = error_token,
4844 };
4845 break :s &payload_val_scope.base;
4846 } else if (if_full.payload_token) |payload_token| {
4847 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;
4848 const tag: Zir.Inst.Tag = if (payload_is_ref)
4849 .optional_payload_unsafe_ptr
4850 else
4851 .optional_payload_unsafe;
4852 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
4853 const ident_name = try astgen.identAsString(ident_token);
4854 payload_val_scope = .{
4855 .parent = &then_scope.base,
4856 .gen_zir = &then_scope,
4857 .name = ident_name,
4858 .inst = payload_inst,
4859 .token_src = ident_token,
4860 };
4861 break :s &payload_val_scope.base;
4862 } else {
4863 break :s &then_scope.base;
4864 }
4865 };
4866
4867 block_scope.break_count += 1;
4868 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, if_full.ast.then_expr);
4869 // We hold off on the break instructions as well as copying the then/else
4870 // instructions into place until we know whether to keep store_to_block_ptr
4871 // instructions or not.
4872
4873 var else_scope = parent_gz.makeSubBlock(scope);
4874 defer else_scope.instructions.deinit(astgen.gpa);
4875
4876 const else_node = if_full.ast.else_expr;
4877 const else_info: struct {
4878 src: ast.Node.Index,
4879 result: Zir.Inst.Ref,
4880 } = if (else_node != 0) blk: {
4881 block_scope.break_count += 1;
4882 const sub_scope = s: {
4883 if (if_full.error_token) |error_token| {
4884 const tag: Zir.Inst.Tag = if (payload_is_ref)
4885 .err_union_code_ptr
4886 else
4887 .err_union_code;
4888 const payload_inst = try else_scope.addUnNode(tag, cond.inst, node);
4889 const ident_name = try astgen.identAsString(error_token);
4890 payload_val_scope = .{
4891 .parent = &else_scope.base,
4892 .gen_zir = &else_scope,
4893 .name = ident_name,
4894 .inst = payload_inst,
4895 .token_src = error_token,
4896 };
4897 break :s &payload_val_scope.base;
4898 } else {
4899 break :s &else_scope.base;
4900 }
4901 };
4902 break :blk .{
4903 .src = else_node,
4904 .result = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node),
4905 };
4906 } else .{
4907 .src = if_full.ast.then_expr,
4908 .result = .none,
4909 };
4910
4911 return finishThenElseBlock(
4912 parent_gz,
4913 scope,
4914 rl,
4915 node,
4916 &block_scope,
4917 &then_scope,
4918 &else_scope,
4919 condbr,
4920 cond.bool_bit,
4921 if_full.ast.then_expr,
4922 else_info.src,
4923 then_result,
4924 else_info.result,
4925 block,
4926 block,
4927 .@"break",
4928 );
4929}
4930
4931fn setCondBrPayload(
4932 condbr: Zir.Inst.Index,
4933 cond: Zir.Inst.Ref,
4934 then_scope: *GenZir,
4935 else_scope: *GenZir,
4936) !void {
4937 const astgen = then_scope.astgen;
4938
4939 try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len +
4940 @typeInfo(Zir.Inst.CondBr).Struct.fields.len +
4941 then_scope.instructions.items.len + else_scope.instructions.items.len);
4942
4943 const zir_datas = astgen.instructions.items(.data);
4944 zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{
4945 .condition = cond,
4946 .then_body_len = @intCast(u32, then_scope.instructions.items.len),
4947 .else_body_len = @intCast(u32, else_scope.instructions.items.len),
4948 });
4949 astgen.extra.appendSliceAssumeCapacity(then_scope.instructions.items);
4950 astgen.extra.appendSliceAssumeCapacity(else_scope.instructions.items);
4951}
4952
4953fn setCondBrPayloadElideBlockStorePtr(
4954 condbr: Zir.Inst.Index,
4955 cond: Zir.Inst.Ref,
4956 then_scope: *GenZir,
4957 else_scope: *GenZir,
4958 block_ptr: Zir.Inst.Ref,
4959) !void {
4960 const astgen = then_scope.astgen;
4961
4962 try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len +
4963 then_scope.instructions.items.len + else_scope.instructions.items.len);
4964
4965 const zir_tags = astgen.instructions.items(.tag);
4966 const zir_datas = astgen.instructions.items(.data);
4967
4968 const condbr_pl = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{
4969 .condition = cond,
4970 .then_body_len = @intCast(u32, then_scope.instructions.items.len),
4971 .else_body_len = @intCast(u32, else_scope.instructions.items.len),
4972 });
4973 zir_datas[condbr].pl_node.payload_index = condbr_pl;
4974 const then_body_len_index = condbr_pl + 1;
4975 const else_body_len_index = condbr_pl + 2;
4976
4977 for (then_scope.instructions.items) |src_inst| {
4978 if (zir_tags[src_inst] == .store_to_block_ptr) {
4979 if (zir_datas[src_inst].bin.lhs == block_ptr) {
4980 astgen.extra.items[then_body_len_index] -= 1;
4981 continue;
4982 }
4983 }
4984 astgen.extra.appendAssumeCapacity(src_inst);
4985 }
4986 for (else_scope.instructions.items) |src_inst| {
4987 if (zir_tags[src_inst] == .store_to_block_ptr) {
4988 if (zir_datas[src_inst].bin.lhs == block_ptr) {
4989 astgen.extra.items[else_body_len_index] -= 1;
4990 continue;
4991 }
4992 }
4993 astgen.extra.appendAssumeCapacity(src_inst);
4994 }
4995}
4996
4997fn whileExpr(
4998 parent_gz: *GenZir,
4999 scope: *Scope,
5000 rl: ResultLoc,
5001 node: ast.Node.Index,
5002 while_full: ast.full.While,
5003) InnerError!Zir.Inst.Ref {
5004 const astgen = parent_gz.astgen;
5005 const tree = astgen.tree;
5006 const token_tags = tree.tokens.items(.tag);
5007
5008 if (while_full.label_token) |label_token| {
5009 try astgen.checkLabelRedefinition(scope, label_token);
5010 }
5011
5012 const is_inline = parent_gz.force_comptime or while_full.inline_token != null;
5013 const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop;
5014 const loop_block = try parent_gz.addBlock(loop_tag, node);
5015 try parent_gz.instructions.append(astgen.gpa, loop_block);
5016
5017 var loop_scope = parent_gz.makeSubBlock(scope);
5018 loop_scope.setBreakResultLoc(rl);
5019 defer loop_scope.instructions.deinit(astgen.gpa);
5020 defer loop_scope.labeled_breaks.deinit(astgen.gpa);
5021 defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);
5022
5023 var continue_scope = parent_gz.makeSubBlock(&loop_scope.base);
5024 defer continue_scope.instructions.deinit(astgen.gpa);
5025
5026 const payload_is_ref = if (while_full.payload_token) |payload_token|
5027 token_tags[payload_token] == .asterisk
5028 else
5029 false;
5030
5031 const cond: struct {
5032 inst: Zir.Inst.Ref,
5033 bool_bit: Zir.Inst.Ref,
5034 } = c: {
5035 if (while_full.error_token) |error_token| {
5036 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;
5037 const err_union = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr);
5038 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_err_ptr else .is_err;
5039 break :c .{
5040 .inst = err_union,
5041 .bool_bit = try continue_scope.addUnNode(tag, err_union, node),
5042 };
5043 } else if (while_full.payload_token) |payload_token| {
5044 const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;
5045 const optional = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr);
5046 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;
5047 break :c .{
5048 .inst = optional,
5049 .bool_bit = try continue_scope.addUnNode(tag, optional, node),
5050 };
5051 } else {
5052 const cond = try expr(&continue_scope, &continue_scope.base, bool_rl, while_full.ast.cond_expr);
5053 break :c .{
5054 .inst = cond,
5055 .bool_bit = cond,
5056 };
5057 }
5058 };
5059
5060 const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;
5061 const condbr = try continue_scope.addCondBr(condbr_tag, node);
5062 const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block;
5063 const cond_block = try loop_scope.addBlock(block_tag, node);
5064 try loop_scope.instructions.append(astgen.gpa, cond_block);
5065 try continue_scope.setBlockBody(cond_block);
5066
5067 // TODO avoid emitting the continue expr when there
5068 // are no jumps to it. This happens when the last statement of a while body is noreturn
5069 // and there are no `continue` statements.
5070 if (while_full.ast.cont_expr != 0) {
5071 _ = try expr(&loop_scope, &loop_scope.base, .{ .ty = .void_type }, while_full.ast.cont_expr);
5072 }
5073 const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
5074 _ = try loop_scope.addNode(repeat_tag, node);
5075
5076 try loop_scope.setBlockBody(loop_block);
5077 loop_scope.break_block = loop_block;
5078 loop_scope.continue_block = cond_block;
5079 if (while_full.label_token) |label_token| {
5080 loop_scope.label = @as(?GenZir.Label, GenZir.Label{
5081 .token = label_token,
5082 .block_inst = loop_block,
5083 });
5084 }
5085
5086 var then_scope = parent_gz.makeSubBlock(&continue_scope.base);
5087 defer then_scope.instructions.deinit(astgen.gpa);
5088
5089 var payload_val_scope: Scope.LocalVal = undefined;
5090
5091 const then_sub_scope = s: {
5092 if (while_full.error_token) |error_token| {
5093 const tag: Zir.Inst.Tag = if (payload_is_ref)
5094 .err_union_payload_unsafe_ptr
5095 else
5096 .err_union_payload_unsafe;
5097 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
5098 const ident_name = try astgen.identAsString(error_token);
5099 payload_val_scope = .{
5100 .parent = &then_scope.base,
5101 .gen_zir = &then_scope,
5102 .name = ident_name,
5103 .inst = payload_inst,
5104 .token_src = error_token,
5105 };
5106 break :s &payload_val_scope.base;
5107 } else if (while_full.payload_token) |payload_token| {
5108 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;
5109 const tag: Zir.Inst.Tag = if (payload_is_ref)
5110 .optional_payload_unsafe_ptr
5111 else
5112 .optional_payload_unsafe;
5113 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
5114 const ident_name = try astgen.identAsString(ident_token);
5115 payload_val_scope = .{
5116 .parent = &then_scope.base,
5117 .gen_zir = &then_scope,
5118 .name = ident_name,
5119 .inst = payload_inst,
5120 .token_src = ident_token,
5121 };
5122 break :s &payload_val_scope.base;
5123 } else {
5124 break :s &then_scope.base;
5125 }
5126 };
5127
5128 loop_scope.break_count += 1;
5129 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr);
5130
5131 var else_scope = parent_gz.makeSubBlock(&continue_scope.base);
5132 defer else_scope.instructions.deinit(astgen.gpa);
5133
5134 const else_node = while_full.ast.else_expr;
5135 const else_info: struct {
5136 src: ast.Node.Index,
5137 result: Zir.Inst.Ref,
5138 } = if (else_node != 0) blk: {
5139 loop_scope.break_count += 1;
5140 const sub_scope = s: {
5141 if (while_full.error_token) |error_token| {
5142 const tag: Zir.Inst.Tag = if (payload_is_ref)
5143 .err_union_code_ptr
5144 else
5145 .err_union_code;
5146 const payload_inst = try else_scope.addUnNode(tag, cond.inst, node);
5147 const ident_name = try astgen.identAsString(error_token);
5148 payload_val_scope = .{
5149 .parent = &else_scope.base,
5150 .gen_zir = &else_scope,
5151 .name = ident_name,
5152 .inst = payload_inst,
5153 .token_src = error_token,
5154 };
5155 break :s &payload_val_scope.base;
5156 } else {
5157 break :s &else_scope.base;
5158 }
5159 };
5160 break :blk .{
5161 .src = else_node,
5162 .result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node),
5163 };
5164 } else .{
5165 .src = while_full.ast.then_expr,
5166 .result = .none,
5167 };
5168
5169 if (loop_scope.label) |some| {
5170 if (!some.used) {
5171 return astgen.failTok(some.token, "unused while loop label", .{});
5172 }
5173 }
5174 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
5175 return finishThenElseBlock(
5176 parent_gz,
5177 scope,
5178 rl,
5179 node,
5180 &loop_scope,
5181 &then_scope,
5182 &else_scope,
5183 condbr,
5184 cond.bool_bit,
5185 while_full.ast.then_expr,
5186 else_info.src,
5187 then_result,
5188 else_info.result,
5189 loop_block,
5190 cond_block,
5191 break_tag,
5192 );
5193}
5194
5195fn forExpr(
5196 parent_gz: *GenZir,
5197 scope: *Scope,
5198 rl: ResultLoc,
5199 node: ast.Node.Index,
5200 for_full: ast.full.While,
5201) InnerError!Zir.Inst.Ref {
5202 const astgen = parent_gz.astgen;
5203
5204 if (for_full.label_token) |label_token| {
5205 try astgen.checkLabelRedefinition(scope, label_token);
5206 }
5207 // Set up variables and constants.
5208 const is_inline = parent_gz.force_comptime or for_full.inline_token != null;
5209 const tree = astgen.tree;
5210 const token_tags = tree.tokens.items(.tag);
5211
5212 const array_ptr = try expr(parent_gz, scope, .ref, for_full.ast.cond_expr);
5213 const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr);
5214
5215 const index_ptr = blk: {
5216 const index_ptr = try parent_gz.addUnNode(.alloc, .usize_type, node);
5217 // initialize to zero
5218 _ = try parent_gz.addBin(.store, index_ptr, .zero_usize);
5219 break :blk index_ptr;
5220 };
5221
5222 const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop;
5223 const loop_block = try parent_gz.addBlock(loop_tag, node);
5224 try parent_gz.instructions.append(astgen.gpa, loop_block);
5225
5226 var loop_scope = parent_gz.makeSubBlock(scope);
5227 loop_scope.setBreakResultLoc(rl);
5228 defer loop_scope.instructions.deinit(astgen.gpa);
5229 defer loop_scope.labeled_breaks.deinit(astgen.gpa);
5230 defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);
5231
5232 var cond_scope = parent_gz.makeSubBlock(&loop_scope.base);
5233 defer cond_scope.instructions.deinit(astgen.gpa);
5234
5235 // check condition i < array_expr.len
5236 const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);
5237 const cond = try cond_scope.addPlNode(.cmp_lt, for_full.ast.cond_expr, Zir.Inst.Bin{
5238 .lhs = index,
5239 .rhs = len,
5240 });
5241
5242 const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;
5243 const condbr = try cond_scope.addCondBr(condbr_tag, node);
5244 const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block;
5245 const cond_block = try loop_scope.addBlock(block_tag, node);
5246 try loop_scope.instructions.append(astgen.gpa, cond_block);
5247 try cond_scope.setBlockBody(cond_block);
5248
5249 // Increment the index variable.
5250 const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);
5251 const index_plus_one = try loop_scope.addPlNode(.add, node, Zir.Inst.Bin{
5252 .lhs = index_2,
5253 .rhs = .one_usize,
5254 });
5255 _ = try loop_scope.addBin(.store, index_ptr, index_plus_one);
5256 const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
5257 _ = try loop_scope.addNode(repeat_tag, node);
5258
5259 try loop_scope.setBlockBody(loop_block);
5260 loop_scope.break_block = loop_block;
5261 loop_scope.continue_block = cond_block;
5262 if (for_full.label_token) |label_token| {
5263 loop_scope.label = @as(?GenZir.Label, GenZir.Label{
5264 .token = label_token,
5265 .block_inst = loop_block,
5266 });
5267 }
5268
5269 var then_scope = parent_gz.makeSubBlock(&cond_scope.base);
5270 defer then_scope.instructions.deinit(astgen.gpa);
5271
5272 var payload_val_scope: Scope.LocalVal = undefined;
5273 var index_scope: Scope.LocalPtr = undefined;
5274 const then_sub_scope = blk: {
5275 const payload_token = for_full.payload_token.?;
5276 const ident = if (token_tags[payload_token] == .asterisk)
5277 payload_token + 1
5278 else
5279 payload_token;
5280 const is_ptr = ident != payload_token;
5281 const value_name = tree.tokenSlice(ident);
5282 var payload_sub_scope: *Scope = undefined;
5283 if (!mem.eql(u8, value_name, "_")) {
5284 const name_str_index = try astgen.identAsString(ident);
5285 const tag: Zir.Inst.Tag = if (is_ptr) .elem_ptr else .elem_val;
5286 const payload_inst = try then_scope.addBin(tag, array_ptr, index);
5287 payload_val_scope = .{
5288 .parent = &then_scope.base,
5289 .gen_zir = &then_scope,
5290 .name = name_str_index,
5291 .inst = payload_inst,
5292 .token_src = ident,
5293 };
5294 payload_sub_scope = &payload_val_scope.base;
5295 } else if (is_ptr) {
5296 return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});
5297 } else {
5298 payload_sub_scope = &then_scope.base;
5299 }
5300
5301 const index_token = if (token_tags[ident + 1] == .comma)
5302 ident + 2
5303 else
5304 break :blk payload_sub_scope;
5305 if (mem.eql(u8, tree.tokenSlice(index_token), "_")) {
5306 return astgen.failTok(index_token, "discard of index capture; omit it instead", .{});
5307 }
5308 const index_name = try astgen.identAsString(index_token);
5309 index_scope = .{
5310 .parent = payload_sub_scope,
5311 .gen_zir = &then_scope,
5312 .name = index_name,
5313 .ptr = index_ptr,
5314 .token_src = index_token,
5315 };
5316 break :blk &index_scope.base;
5317 };
5318
5319 loop_scope.break_count += 1;
5320 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr);
5321
5322 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
5323 defer else_scope.instructions.deinit(astgen.gpa);
5324
5325 const else_node = for_full.ast.else_expr;
5326 const else_info: struct {
5327 src: ast.Node.Index,
5328 result: Zir.Inst.Ref,
5329 } = if (else_node != 0) blk: {
5330 loop_scope.break_count += 1;
5331 const sub_scope = &else_scope.base;
5332 break :blk .{
5333 .src = else_node,
5334 .result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node),
5335 };
5336 } else .{
5337 .src = for_full.ast.then_expr,
5338 .result = .none,
5339 };
5340
5341 if (loop_scope.label) |some| {
5342 if (!some.used) {
5343 return astgen.failTok(some.token, "unused for loop label", .{});
5344 }
5345 }
5346 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
5347 return finishThenElseBlock(
5348 parent_gz,
5349 scope,
5350 rl,
5351 node,
5352 &loop_scope,
5353 &then_scope,
5354 &else_scope,
5355 condbr,
5356 cond,
5357 for_full.ast.then_expr,
5358 else_info.src,
5359 then_result,
5360 else_info.result,
5361 loop_block,
5362 cond_block,
5363 break_tag,
5364 );
5365}
5366
5367fn switchExpr(
5368 parent_gz: *GenZir,
5369 scope: *Scope,
5370 rl: ResultLoc,
5371 switch_node: ast.Node.Index,
5372) InnerError!Zir.Inst.Ref {
5373 const astgen = parent_gz.astgen;
5374 const gpa = astgen.gpa;
5375 const tree = astgen.tree;
5376 const node_datas = tree.nodes.items(.data);
5377 const node_tags = tree.nodes.items(.tag);
5378 const main_tokens = tree.nodes.items(.main_token);
5379 const token_tags = tree.tokens.items(.tag);
5380 const operand_node = node_datas[switch_node].lhs;
5381 const extra = tree.extraData(node_datas[switch_node].rhs, ast.Node.SubRange);
5382 const case_nodes = tree.extra_data[extra.start..extra.end];
5383
5384 // We perform two passes over the AST. This first pass is to collect information
5385 // for the following variables, make note of the special prong AST node index,
5386 // and bail out with a compile error if there are multiple special prongs present.
5387 var any_payload_is_ref = false;
5388 var scalar_cases_len: u32 = 0;
5389 var multi_cases_len: u32 = 0;
5390 var special_prong: Zir.SpecialProng = .none;
5391 var special_node: ast.Node.Index = 0;
5392 var else_src: ?ast.TokenIndex = null;
5393 var underscore_src: ?ast.TokenIndex = null;
5394 for (case_nodes) |case_node| {
5395 const case = switch (node_tags[case_node]) {
5396 .switch_case_one => tree.switchCaseOne(case_node),
5397 .switch_case => tree.switchCase(case_node),
5398 else => unreachable,
5399 };
5400 if (case.payload_token) |payload_token| {
5401 if (token_tags[payload_token] == .asterisk) {
5402 any_payload_is_ref = true;
5403 }
5404 }
5405 // Check for else/`_` prong.
5406 if (case.ast.values.len == 0) {
5407 const case_src = case.ast.arrow_token - 1;
5408 if (else_src) |src| {
5409 return astgen.failTokNotes(
5410 case_src,
5411 "multiple else prongs in switch expression",
5412 .{},
5413 &[_]u32{
5414 try astgen.errNoteTok(
5415 src,
5416 "previous else prong is here",
5417 .{},
5418 ),
5419 },
5420 );
5421 } else if (underscore_src) |some_underscore| {
5422 return astgen.failNodeNotes(
5423 switch_node,
5424 "else and '_' prong in switch expression",
5425 .{},
5426 &[_]u32{
5427 try astgen.errNoteTok(
5428 case_src,
5429 "else prong is here",
5430 .{},
5431 ),
5432 try astgen.errNoteTok(
5433 some_underscore,
5434 "'_' prong is here",
5435 .{},
5436 ),
5437 },
5438 );
5439 }
5440 special_node = case_node;
5441 special_prong = .@"else";
5442 else_src = case_src;
5443 continue;
5444 } else if (case.ast.values.len == 1 and
5445 node_tags[case.ast.values[0]] == .identifier and
5446 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
5447 {
5448 const case_src = case.ast.arrow_token - 1;
5449 if (underscore_src) |src| {
5450 return astgen.failTokNotes(
5451 case_src,
5452 "multiple '_' prongs in switch expression",
5453 .{},
5454 &[_]u32{
5455 try astgen.errNoteTok(
5456 src,
5457 "previous '_' prong is here",
5458 .{},
5459 ),
5460 },
5461 );
5462 } else if (else_src) |some_else| {
5463 return astgen.failNodeNotes(
5464 switch_node,
5465 "else and '_' prong in switch expression",
5466 .{},
5467 &[_]u32{
5468 try astgen.errNoteTok(
5469 some_else,
5470 "else prong is here",
5471 .{},
5472 ),
5473 try astgen.errNoteTok(
5474 case_src,
5475 "'_' prong is here",
5476 .{},
5477 ),
5478 },
5479 );
5480 }
5481 special_node = case_node;
5482 special_prong = .under;
5483 underscore_src = case_src;
5484 continue;
5485 }
5486
5487 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {
5488 scalar_cases_len += 1;
5489 } else {
5490 multi_cases_len += 1;
5491 }
5492 }
5493
5494 const operand_rl: ResultLoc = if (any_payload_is_ref) .ref else .none;
5495 const operand = try expr(parent_gz, scope, operand_rl, operand_node);
5496 // We need the type of the operand to use as the result location for all the prong items.
5497 const typeof_tag: Zir.Inst.Tag = if (any_payload_is_ref) .typeof_elem else .typeof;
5498 const operand_ty_inst = try parent_gz.addUnNode(typeof_tag, operand, operand_node);
5499 const item_rl: ResultLoc = .{ .ty = operand_ty_inst };
5500
5501 // Contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti.
5502 // This is the header as well as the optional else prong body, as well as all the
5503 // scalar cases.
5504 // At the end we will memcpy this into place.
5505 var scalar_cases_payload = ArrayListUnmanaged(u32){};
5506 defer scalar_cases_payload.deinit(gpa);
5507 // Same deal, but this is only the `extra` data for the multi cases.
5508 var multi_cases_payload = ArrayListUnmanaged(u32){};
5509 defer multi_cases_payload.deinit(gpa);
5510
5511 var block_scope = parent_gz.makeSubBlock(scope);
5512 block_scope.setBreakResultLoc(rl);
5513 defer block_scope.instructions.deinit(gpa);
5514
5515 // This gets added to the parent block later, after the item expressions.
5516 const switch_block = try parent_gz.addBlock(undefined, switch_node);
5517
5518 // We re-use this same scope for all cases, including the special prong, if any.
5519 var case_scope = parent_gz.makeSubBlock(&block_scope.base);
5520 defer case_scope.instructions.deinit(gpa);
5521
5522 // Do the else/`_` first because it goes first in the payload.
5523 var capture_val_scope: Scope.LocalVal = undefined;
5524 if (special_node != 0) {
5525 const case = switch (node_tags[special_node]) {
5526 .switch_case_one => tree.switchCaseOne(special_node),
5527 .switch_case => tree.switchCase(special_node),
5528 else => unreachable,
5529 };
5530 const sub_scope = blk: {
5531 const payload_token = case.payload_token orelse break :blk &case_scope.base;
5532 const ident = if (token_tags[payload_token] == .asterisk)
5533 payload_token + 1
5534 else
5535 payload_token;
5536 const is_ptr = ident != payload_token;
5537 if (mem.eql(u8, tree.tokenSlice(ident), "_")) {
5538 if (is_ptr) {
5539 return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});
5540 }
5541 break :blk &case_scope.base;
5542 }
5543 const capture_tag: Zir.Inst.Tag = if (is_ptr)
5544 .switch_capture_else_ref
5545 else
5546 .switch_capture_else;
5547 const capture = try case_scope.add(.{
5548 .tag = capture_tag,
5549 .data = .{ .switch_capture = .{
5550 .switch_inst = switch_block,
5551 .prong_index = undefined,
5552 } },
5553 });
5554 const capture_name = try astgen.identAsString(payload_token);
5555 capture_val_scope = .{
5556 .parent = &case_scope.base,
5557 .gen_zir = &case_scope,
5558 .name = capture_name,
5559 .inst = capture,
5560 .token_src = payload_token,
5561 };
5562 break :blk &capture_val_scope.base;
5563 };
5564 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);
5565 if (!parent_gz.refIsNoReturn(case_result)) {
5566 block_scope.break_count += 1;
5567 _ = try case_scope.addBreak(.@"break", switch_block, case_result);
5568 }
5569 // Documentation for this: `Zir.Inst.SwitchBlock` and `Zir.Inst.SwitchBlockMulti`.
5570 try scalar_cases_payload.ensureCapacity(gpa, scalar_cases_payload.items.len +
5571 3 + // operand, scalar_cases_len, else body len
5572 @boolToInt(multi_cases_len != 0) +
5573 case_scope.instructions.items.len);
5574 scalar_cases_payload.appendAssumeCapacity(@enumToInt(operand));
5575 scalar_cases_payload.appendAssumeCapacity(scalar_cases_len);
5576 if (multi_cases_len != 0) {
5577 scalar_cases_payload.appendAssumeCapacity(multi_cases_len);
5578 }
5579 scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len));
5580 scalar_cases_payload.appendSliceAssumeCapacity(case_scope.instructions.items);
5581 } else {
5582 // Documentation for this: `Zir.Inst.SwitchBlock` and `Zir.Inst.SwitchBlockMulti`.
5583 try scalar_cases_payload.ensureCapacity(gpa, scalar_cases_payload.items.len +
5584 2 + // operand, scalar_cases_len
5585 @boolToInt(multi_cases_len != 0));
5586 scalar_cases_payload.appendAssumeCapacity(@enumToInt(operand));
5587 scalar_cases_payload.appendAssumeCapacity(scalar_cases_len);
5588 if (multi_cases_len != 0) {
5589 scalar_cases_payload.appendAssumeCapacity(multi_cases_len);
5590 }
5591 }
5592
5593 // In this pass we generate all the item and prong expressions except the special case.
5594 var multi_case_index: u32 = 0;
5595 var scalar_case_index: u32 = 0;
5596 for (case_nodes) |case_node| {
5597 if (case_node == special_node)
5598 continue;
5599 const case = switch (node_tags[case_node]) {
5600 .switch_case_one => tree.switchCaseOne(case_node),
5601 .switch_case => tree.switchCase(case_node),
5602 else => unreachable,
5603 };
5604
5605 // Reset the scope.
5606 case_scope.instructions.shrinkRetainingCapacity(0);
5607
5608 const is_multi_case = case.ast.values.len != 1 or
5609 node_tags[case.ast.values[0]] == .switch_range;
5610
5611 const sub_scope = blk: {
5612 const payload_token = case.payload_token orelse break :blk &case_scope.base;
5613 const ident = if (token_tags[payload_token] == .asterisk)
5614 payload_token + 1
5615 else
5616 payload_token;
5617 const is_ptr = ident != payload_token;
5618 if (mem.eql(u8, tree.tokenSlice(ident), "_")) {
5619 if (is_ptr) {
5620 return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});
5621 }
5622 break :blk &case_scope.base;
5623 }
5624 const is_multi_case_bits: u2 = @boolToInt(is_multi_case);
5625 const is_ptr_bits: u2 = @boolToInt(is_ptr);
5626 const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) {
5627 0b00 => .switch_capture,
5628 0b01 => .switch_capture_ref,
5629 0b10 => .switch_capture_multi,
5630 0b11 => .switch_capture_multi_ref,
5631 };
5632 const capture_index = if (is_multi_case) ci: {
5633 multi_case_index += 1;
5634 break :ci multi_case_index - 1;
5635 } else ci: {
5636 scalar_case_index += 1;
5637 break :ci scalar_case_index - 1;
5638 };
5639 const capture = try case_scope.add(.{
5640 .tag = capture_tag,
5641 .data = .{ .switch_capture = .{
5642 .switch_inst = switch_block,
5643 .prong_index = capture_index,
5644 } },
5645 });
5646 const capture_name = try astgen.identAsString(ident);
5647 capture_val_scope = .{
5648 .parent = &case_scope.base,
5649 .gen_zir = &case_scope,
5650 .name = capture_name,
5651 .inst = capture,
5652 .token_src = payload_token,
5653 };
5654 break :blk &capture_val_scope.base;
5655 };
5656
5657 if (is_multi_case) {
5658 // items_len, ranges_len, body_len
5659 const header_index = multi_cases_payload.items.len;
5660 try multi_cases_payload.resize(gpa, multi_cases_payload.items.len + 3);
5661
5662 // items
5663 var items_len: u32 = 0;
5664 for (case.ast.values) |item_node| {
5665 if (node_tags[item_node] == .switch_range) continue;
5666 items_len += 1;
5667
5668 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);
5669 try multi_cases_payload.append(gpa, @enumToInt(item_inst));
5670 }
5671
5672 // ranges
5673 var ranges_len: u32 = 0;
5674 for (case.ast.values) |range| {
5675 if (node_tags[range] != .switch_range) continue;
5676 ranges_len += 1;
5677
5678 const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs);
5679 const last = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].rhs);
5680 try multi_cases_payload.appendSlice(gpa, &[_]u32{
5681 @enumToInt(first), @enumToInt(last),
5682 });
5683 }
5684
5685 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);
5686 if (!parent_gz.refIsNoReturn(case_result)) {
5687 block_scope.break_count += 1;
5688 _ = try case_scope.addBreak(.@"break", switch_block, case_result);
5689 }
5690
5691 multi_cases_payload.items[header_index + 0] = items_len;
5692 multi_cases_payload.items[header_index + 1] = ranges_len;
5693 multi_cases_payload.items[header_index + 2] = @intCast(u32, case_scope.instructions.items.len);
5694 try multi_cases_payload.appendSlice(gpa, case_scope.instructions.items);
5695 } else {
5696 const item_node = case.ast.values[0];
5697 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);
5698 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);
5699 if (!parent_gz.refIsNoReturn(case_result)) {
5700 block_scope.break_count += 1;
5701 _ = try case_scope.addBreak(.@"break", switch_block, case_result);
5702 }
5703 try scalar_cases_payload.ensureCapacity(gpa, scalar_cases_payload.items.len +
5704 2 + case_scope.instructions.items.len);
5705 scalar_cases_payload.appendAssumeCapacity(@enumToInt(item_inst));
5706 scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len));
5707 scalar_cases_payload.appendSliceAssumeCapacity(case_scope.instructions.items);
5708 }
5709 }
5710 // Now that the item expressions are generated we can add this.
5711 try parent_gz.instructions.append(gpa, switch_block);
5712
5713 const ref_bit: u4 = @boolToInt(any_payload_is_ref);
5714 const multi_bit: u4 = @boolToInt(multi_cases_len != 0);
5715 const special_prong_bits: u4 = @enumToInt(special_prong);
5716 comptime {
5717 assert(@enumToInt(Zir.SpecialProng.none) == 0b00);
5718 assert(@enumToInt(Zir.SpecialProng.@"else") == 0b01);
5719 assert(@enumToInt(Zir.SpecialProng.under) == 0b10);
5720 }
5721 const zir_tags = astgen.instructions.items(.tag);
5722 zir_tags[switch_block] = switch ((ref_bit << 3) | (special_prong_bits << 1) | multi_bit) {
5723 0b0_00_0 => .switch_block,
5724 0b0_00_1 => .switch_block_multi,
5725 0b0_01_0 => .switch_block_else,
5726 0b0_01_1 => .switch_block_else_multi,
5727 0b0_10_0 => .switch_block_under,
5728 0b0_10_1 => .switch_block_under_multi,
5729 0b1_00_0 => .switch_block_ref,
5730 0b1_00_1 => .switch_block_ref_multi,
5731 0b1_01_0 => .switch_block_ref_else,
5732 0b1_01_1 => .switch_block_ref_else_multi,
5733 0b1_10_0 => .switch_block_ref_under,
5734 0b1_10_1 => .switch_block_ref_under_multi,
5735 else => unreachable,
5736 };
5737 const payload_index = astgen.extra.items.len;
5738 const zir_datas = astgen.instructions.items(.data);
5739 zir_datas[switch_block].pl_node.payload_index = @intCast(u32, payload_index);
5740 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
5741 scalar_cases_payload.items.len + multi_cases_payload.items.len);
5742 const strat = rl.strategy(&block_scope);
5743 switch (strat.tag) {
5744 .break_operand => {
5745 // Switch expressions return `true` for `nodeMayNeedMemoryLocation` thus
5746 // `elide_store_to_block_ptr_instructions` will either be true,
5747 // or all prongs are noreturn.
5748 if (!strat.elide_store_to_block_ptr_instructions) {
5749 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items);
5750 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items);
5751 return parent_gz.indexToRef(switch_block);
5752 }
5753
5754 // There will necessarily be a store_to_block_ptr for
5755 // all prongs, except for prongs that ended with a noreturn instruction.
5756 // Elide all the `store_to_block_ptr` instructions.
5757
5758 // The break instructions need to have their operands coerced if the
5759 // switch's result location is a `ty`. In this case we overwrite the
5760 // `store_to_block_ptr` instruction with an `as` instruction and repurpose
5761 // it as the break operand.
5762
5763 var extra_index: usize = 0;
5764 extra_index += 2;
5765 extra_index += @boolToInt(multi_cases_len != 0);
5766 if (special_prong != .none) special_prong: {
5767 const body_len_index = extra_index;
5768 const body_len = scalar_cases_payload.items[extra_index];
5769 extra_index += 1;
5770 if (body_len < 2) {
5771 extra_index += body_len;
5772 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]);
5773 break :special_prong;
5774 }
5775 extra_index += body_len - 2;
5776 const store_inst = scalar_cases_payload.items[extra_index];
5777 if (zir_tags[store_inst] != .store_to_block_ptr or
5778 zir_datas[store_inst].bin.lhs != block_scope.rl_ptr)
5779 {
5780 extra_index += 2;
5781 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]);
5782 break :special_prong;
5783 }
5784 assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr);
5785 if (block_scope.rl_ty_inst != .none) {
5786 extra_index += 1;
5787 const break_inst = scalar_cases_payload.items[extra_index];
5788 extra_index += 1;
5789 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]);
5790 zir_tags[store_inst] = .as;
5791 zir_datas[store_inst].bin = .{
5792 .lhs = block_scope.rl_ty_inst,
5793 .rhs = zir_datas[break_inst].@"break".operand,
5794 };
5795 zir_datas[break_inst].@"break".operand = parent_gz.indexToRef(store_inst);
5796 } else {
5797 scalar_cases_payload.items[body_len_index] -= 1;
5798 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]);
5799 extra_index += 1;
5800 astgen.extra.appendAssumeCapacity(scalar_cases_payload.items[extra_index]);
5801 extra_index += 1;
5802 }
5803 } else {
5804 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]);
5805 }
5806 var scalar_i: u32 = 0;
5807 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
5808 const start_index = extra_index;
5809 extra_index += 1;
5810 const body_len_index = extra_index;
5811 const body_len = scalar_cases_payload.items[extra_index];
5812 extra_index += 1;
5813 if (body_len < 2) {
5814 extra_index += body_len;
5815 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
5816 continue;
5817 }
5818 extra_index += body_len - 2;
5819 const store_inst = scalar_cases_payload.items[extra_index];
5820 if (zir_tags[store_inst] != .store_to_block_ptr or
5821 zir_datas[store_inst].bin.lhs != block_scope.rl_ptr)
5822 {
5823 extra_index += 2;
5824 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
5825 continue;
5826 }
5827 if (block_scope.rl_ty_inst != .none) {
5828 extra_index += 1;
5829 const break_inst = scalar_cases_payload.items[extra_index];
5830 extra_index += 1;
5831 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
5832 zir_tags[store_inst] = .as;
5833 zir_datas[store_inst].bin = .{
5834 .lhs = block_scope.rl_ty_inst,
5835 .rhs = zir_datas[break_inst].@"break".operand,
5836 };
5837 zir_datas[break_inst].@"break".operand = parent_gz.indexToRef(store_inst);
5838 } else {
5839 scalar_cases_payload.items[body_len_index] -= 1;
5840 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
5841 extra_index += 1;
5842 astgen.extra.appendAssumeCapacity(scalar_cases_payload.items[extra_index]);
5843 extra_index += 1;
5844 }
5845 }
5846 extra_index = 0;
5847 var multi_i: u32 = 0;
5848 while (multi_i < multi_cases_len) : (multi_i += 1) {
5849 const start_index = extra_index;
5850 const items_len = multi_cases_payload.items[extra_index];
5851 extra_index += 1;
5852 const ranges_len = multi_cases_payload.items[extra_index];
5853 extra_index += 1;
5854 const body_len_index = extra_index;
5855 const body_len = multi_cases_payload.items[extra_index];
5856 extra_index += 1;
5857 extra_index += items_len;
5858 extra_index += 2 * ranges_len;
5859 if (body_len < 2) {
5860 extra_index += body_len;
5861 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
5862 continue;
5863 }
5864 extra_index += body_len - 2;
5865 const store_inst = multi_cases_payload.items[extra_index];
5866 if (zir_tags[store_inst] != .store_to_block_ptr or
5867 zir_datas[store_inst].bin.lhs != block_scope.rl_ptr)
5868 {
5869 extra_index += 2;
5870 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
5871 continue;
5872 }
5873 if (block_scope.rl_ty_inst != .none) {
5874 extra_index += 1;
5875 const break_inst = multi_cases_payload.items[extra_index];
5876 extra_index += 1;
5877 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
5878 zir_tags[store_inst] = .as;
5879 zir_datas[store_inst].bin = .{
5880 .lhs = block_scope.rl_ty_inst,
5881 .rhs = zir_datas[break_inst].@"break".operand,
5882 };
5883 zir_datas[break_inst].@"break".operand = parent_gz.indexToRef(store_inst);
5884 } else {
5885 assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr);
5886 multi_cases_payload.items[body_len_index] -= 1;
5887 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
5888 extra_index += 1;
5889 astgen.extra.appendAssumeCapacity(multi_cases_payload.items[extra_index]);
5890 extra_index += 1;
5891 }
5892 }
5893
5894 const block_ref = parent_gz.indexToRef(switch_block);
5895 switch (rl) {
5896 .ref => return block_ref,
5897 else => return rvalue(parent_gz, scope, rl, block_ref, switch_node),
5898 }
5899 },
5900 .break_void => {
5901 assert(!strat.elide_store_to_block_ptr_instructions);
5902 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items);
5903 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items);
5904 // Modify all the terminating instruction tags to become `break` variants.
5905 var extra_index: usize = payload_index;
5906 extra_index += 2;
5907 extra_index += @boolToInt(multi_cases_len != 0);
5908 if (special_prong != .none) {
5909 const body_len = astgen.extra.items[extra_index];
5910 extra_index += 1;
5911 const body = astgen.extra.items[extra_index..][0..body_len];
5912 extra_index += body_len;
5913 const last = body[body.len - 1];
5914 if (zir_tags[last] == .@"break" and
5915 zir_datas[last].@"break".block_inst == switch_block)
5916 {
5917 zir_datas[last].@"break".operand = .void_value;
5918 }
5919 }
5920 var scalar_i: u32 = 0;
5921 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
5922 extra_index += 1;
5923 const body_len = astgen.extra.items[extra_index];
5924 extra_index += 1;
5925 const body = astgen.extra.items[extra_index..][0..body_len];
5926 extra_index += body_len;
5927 const last = body[body.len - 1];
5928 if (zir_tags[last] == .@"break" and
5929 zir_datas[last].@"break".block_inst == switch_block)
5930 {
5931 zir_datas[last].@"break".operand = .void_value;
5932 }
5933 }
5934 var multi_i: u32 = 0;
5935 while (multi_i < multi_cases_len) : (multi_i += 1) {
5936 const items_len = astgen.extra.items[extra_index];
5937 extra_index += 1;
5938 const ranges_len = astgen.extra.items[extra_index];
5939 extra_index += 1;
5940 const body_len = astgen.extra.items[extra_index];
5941 extra_index += 1;
5942 extra_index += items_len;
5943 extra_index += 2 * ranges_len;
5944 const body = astgen.extra.items[extra_index..][0..body_len];
5945 extra_index += body_len;
5946 const last = body[body.len - 1];
5947 if (zir_tags[last] == .@"break" and
5948 zir_datas[last].@"break".block_inst == switch_block)
5949 {
5950 zir_datas[last].@"break".operand = .void_value;
5951 }
5952 }
5953
5954 return parent_gz.indexToRef(switch_block);
5955 },
5956 }
5957}
5958
5959fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
5960 const astgen = gz.astgen;
5961 const tree = astgen.tree;
5962 const node_datas = tree.nodes.items(.data);
5963 const main_tokens = tree.nodes.items(.main_token);
5964
5965 const operand_node = node_datas[node].lhs;
5966 if (operand_node != 0) {
5967 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node)) .{
5968 .ptr = try gz.addNodeExtended(.ret_ptr, node),
5969 } else .{
5970 .ty = try gz.addNodeExtended(.ret_type, node),
5971 };
5972 const operand = try expr(gz, scope, rl, operand_node);
5973 // TODO check operand to see if we need to generate errdefers
5974 try genDefers(gz, &astgen.fn_block.?.base, scope, .none);
5975 _ = try gz.addUnNode(.ret_node, operand, node);
5976 return Zir.Inst.Ref.unreachable_value;
5977 }
5978 // Returning a void value; skip error defers.
5979 try genDefers(gz, &astgen.fn_block.?.base, scope, .none);
5980 _ = try gz.addUnNode(.ret_node, .void_value, node);
5981 return Zir.Inst.Ref.unreachable_value;
5982}
5983
5984fn identifier(
5985 gz: *GenZir,
5986 scope: *Scope,
5987 rl: ResultLoc,
5988 ident: ast.Node.Index,
5989) InnerError!Zir.Inst.Ref {
5990 const tracy = trace(@src());
5991 defer tracy.end();
5992
5993 const astgen = gz.astgen;
5994 const tree = astgen.tree;
5995 const main_tokens = tree.nodes.items(.main_token);
5996
5997 const ident_token = main_tokens[ident];
5998 const ident_name = try astgen.identifierTokenString(ident_token);
5999 if (mem.eql(u8, ident_name, "_")) {
6000 return astgen.failNode(ident, "'_' may not be used as an identifier", .{});
6001 }
6002
6003 if (simple_types.get(ident_name)) |zir_const_ref| {
6004 return rvalue(gz, scope, rl, zir_const_ref, ident);
6005 }
6006
6007 if (ident_name.len >= 2) integer: {
6008 const first_c = ident_name[0];
6009 if (first_c == 'i' or first_c == 'u') {
6010 const signedness: std.builtin.Signedness = switch (first_c == 'i') {
6011 true => .signed,
6012 false => .unsigned,
6013 };
6014 const bit_count = std.fmt.parseInt(u16, ident_name[1..], 10) catch |err| switch (err) {
6015 error.Overflow => return astgen.failNode(
6016 ident,
6017 "primitive integer type '{s}' exceeds maximum bit width of 65535",
6018 .{ident_name},
6019 ),
6020 error.InvalidCharacter => break :integer,
6021 };
6022 const result = try gz.add(.{
6023 .tag = .int_type,
6024 .data = .{ .int_type = .{
6025 .src_node = gz.nodeIndexToRelative(ident),
6026 .signedness = signedness,
6027 .bit_count = bit_count,
6028 } },
6029 });
6030 return rvalue(gz, scope, rl, result, ident);
6031 }
6032 }
6033
6034 // Local variables, including function parameters.
6035 const name_str_index = try astgen.identAsString(ident_token);
6036 {
6037 var s = scope;
6038 while (true) switch (s.tag) {
6039 .local_val => {
6040 const local_val = s.cast(Scope.LocalVal).?;
6041 if (local_val.name == name_str_index) {
6042 return rvalue(gz, scope, rl, local_val.inst, ident);
6043 }
6044 s = local_val.parent;
6045 },
6046 .local_ptr => {
6047 const local_ptr = s.cast(Scope.LocalPtr).?;
6048 if (local_ptr.name == name_str_index) {
6049 switch (rl) {
6050 .ref, .none_or_ref => return local_ptr.ptr,
6051 else => {
6052 const loaded = try gz.addUnNode(.load, local_ptr.ptr, ident);
6053 return rvalue(gz, scope, rl, loaded, ident);
6054 },
6055 }
6056 }
6057 s = local_ptr.parent;
6058 },
6059 .gen_zir => s = s.cast(GenZir).?.parent,
6060 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
6061 .namespace, .top => break, // TODO look for ambiguous references to decls
6062 };
6063 }
6064
6065 // We can't look up Decls until Sema because the same ZIR code is supposed to be
6066 // used for multiple generic instantiations, and this may refer to a different Decl
6067 // depending on the scope, determined by the generic instantiation.
6068 switch (rl) {
6069 .ref, .none_or_ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token),
6070 else => {
6071 const result = try gz.addStrTok(.decl_val, name_str_index, ident_token);
6072 return rvalue(gz, scope, rl, result, ident);
6073 },
6074 }
6075}
6076
6077fn stringLiteral(
6078 gz: *GenZir,
6079 scope: *Scope,
6080 rl: ResultLoc,
6081 node: ast.Node.Index,
6082) InnerError!Zir.Inst.Ref {
6083 const astgen = gz.astgen;
6084 const tree = astgen.tree;
6085 const main_tokens = tree.nodes.items(.main_token);
6086 const str_lit_token = main_tokens[node];
6087 const str = try astgen.strLitAsString(str_lit_token);
6088 const result = try gz.add(.{
6089 .tag = .str,
6090 .data = .{ .str = .{
6091 .start = str.index,
6092 .len = str.len,
6093 } },
6094 });
6095 return rvalue(gz, scope, rl, result, node);
6096}
6097
6098fn multilineStringLiteral(
6099 gz: *GenZir,
6100 scope: *Scope,
6101 rl: ResultLoc,
6102 node: ast.Node.Index,
6103) InnerError!Zir.Inst.Ref {
6104 const astgen = gz.astgen;
6105 const tree = astgen.tree;
6106 const node_datas = tree.nodes.items(.data);
6107 const main_tokens = tree.nodes.items(.main_token);
6108
6109 const start = node_datas[node].lhs;
6110 const end = node_datas[node].rhs;
6111
6112 const gpa = gz.astgen.gpa;
6113 const string_bytes = &gz.astgen.string_bytes;
6114 const str_index = string_bytes.items.len;
6115
6116 // First line: do not append a newline.
6117 var tok_i = start;
6118 {
6119 const slice = tree.tokenSlice(tok_i);
6120 const line_bytes = slice[2 .. slice.len - 1];
6121 try string_bytes.appendSlice(gpa, line_bytes);
6122 tok_i += 1;
6123 }
6124 // Following lines: each line prepends a newline.
6125 while (tok_i <= end) : (tok_i += 1) {
6126 const slice = tree.tokenSlice(tok_i);
6127 const line_bytes = slice[2 .. slice.len - 1];
6128 try string_bytes.ensureCapacity(gpa, string_bytes.items.len + line_bytes.len + 1);
6129 string_bytes.appendAssumeCapacity('\n');
6130 string_bytes.appendSliceAssumeCapacity(line_bytes);
6131 }
6132 const result = try gz.add(.{
6133 .tag = .str,
6134 .data = .{ .str = .{
6135 .start = @intCast(u32, str_index),
6136 .len = @intCast(u32, string_bytes.items.len - str_index),
6137 } },
6138 });
6139 return rvalue(gz, scope, rl, result, node);
6140}
6141
6142fn charLiteral(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {
6143 const astgen = gz.astgen;
6144 const tree = astgen.tree;
6145 const main_tokens = tree.nodes.items(.main_token);
6146 const main_token = main_tokens[node];
6147 const slice = tree.tokenSlice(main_token);
6148
6149 var bad_index: usize = undefined;
6150 const value = std.zig.parseCharLiteral(slice, &bad_index) catch |err| switch (err) {
6151 error.InvalidCharacter => {
6152 const bad_byte = slice[bad_index];
6153 return astgen.failOff(
6154 main_token,
6155 @intCast(u32, bad_index),
6156 "invalid character: '{c}'\n",
6157 .{bad_byte},
6158 );
6159 },
6160 };
6161 const result = try gz.addInt(value);
6162 return rvalue(gz, scope, rl, result, node);
6163}
6164
6165fn integerLiteral(
6166 gz: *GenZir,
6167 scope: *Scope,
6168 rl: ResultLoc,
6169 node: ast.Node.Index,
6170) InnerError!Zir.Inst.Ref {
6171 const astgen = gz.astgen;
6172 const tree = astgen.tree;
6173 const main_tokens = tree.nodes.items(.main_token);
6174 const int_token = main_tokens[node];
6175 const prefixed_bytes = tree.tokenSlice(int_token);
6176 if (std.fmt.parseInt(u64, prefixed_bytes, 0)) |small_int| {
6177 const result: Zir.Inst.Ref = switch (small_int) {
6178 0 => .zero,
6179 1 => .one,
6180 else => try gz.addInt(small_int),
6181 };
6182 return rvalue(gz, scope, rl, result, node);
6183 } else |err| switch (err) {
6184 error.InvalidCharacter => unreachable, // Caught by the parser.
6185 error.Overflow => {},
6186 }
6187
6188 var base: u8 = 10;
6189 var non_prefixed: []const u8 = prefixed_bytes;
6190 if (mem.startsWith(u8, prefixed_bytes, "0x")) {
6191 base = 16;
6192 non_prefixed = prefixed_bytes[2..];
6193 } else if (mem.startsWith(u8, prefixed_bytes, "0o")) {
6194 base = 8;
6195 non_prefixed = prefixed_bytes[2..];
6196 } else if (mem.startsWith(u8, prefixed_bytes, "0b")) {
6197 base = 2;
6198 non_prefixed = prefixed_bytes[2..];
6199 }
6200
6201 const gpa = astgen.gpa;
6202 var big_int = try std.math.big.int.Managed.init(gpa);
6203 defer big_int.deinit();
6204 big_int.setString(base, non_prefixed) catch |err| switch (err) {
6205 error.InvalidCharacter => unreachable, // caught by parser
6206 error.InvalidBase => unreachable, // we only pass 16, 8, 2, see above
6207 error.OutOfMemory => return error.OutOfMemory,
6208 };
6209
6210 const limbs = big_int.limbs[0..big_int.len()];
6211 assert(big_int.isPositive());
6212 const result = try gz.addIntBig(limbs);
6213 return rvalue(gz, scope, rl, result, node);
6214}
6215
6216fn floatLiteral(
6217 gz: *GenZir,
6218 scope: *Scope,
6219 rl: ResultLoc,
6220 node: ast.Node.Index,
6221) InnerError!Zir.Inst.Ref {
6222 const astgen = gz.astgen;
6223 const arena = astgen.arena;
6224 const tree = astgen.tree;
6225 const main_tokens = tree.nodes.items(.main_token);
6226
6227 const main_token = main_tokens[node];
6228 const bytes = tree.tokenSlice(main_token);
6229 const float_number: f128 = if (bytes.len > 2 and bytes[1] == 'x') hex: {
6230 assert(bytes[0] == '0'); // validated by tokenizer
6231 break :hex std.fmt.parseHexFloat(f128, bytes) catch |err| switch (err) {
6232 error.InvalidCharacter => unreachable, // validated by tokenizer
6233 error.Overflow => return astgen.failNode(node, "number literal cannot be represented in a 128-bit floating point", .{}),
6234 };
6235 } else std.fmt.parseFloat(f128, bytes) catch |err| switch (err) {
6236 error.InvalidCharacter => unreachable, // validated by tokenizer
6237 };
6238 // If the value fits into a f32 without losing any precision, store it that way.
6239 @setFloatMode(.Strict);
6240 const smaller_float = @floatCast(f32, float_number);
6241 const bigger_again: f128 = smaller_float;
6242 if (bigger_again == float_number) {
6243 const result = try gz.addFloat(smaller_float, node);
6244 return rvalue(gz, scope, rl, result, node);
6245 }
6246 // We need to use 128 bits. Break the float into 4 u32 values so we can
6247 // put it into the `extra` array.
6248 const int_bits = @bitCast(u128, float_number);
6249 const result = try gz.addPlNode(.float128, node, Zir.Inst.Float128{
6250 .piece0 = @truncate(u32, int_bits),
6251 .piece1 = @truncate(u32, int_bits >> 32),
6252 .piece2 = @truncate(u32, int_bits >> 64),
6253 .piece3 = @truncate(u32, int_bits >> 96),
6254 });
6255 return rvalue(gz, scope, rl, result, node);
6256}
6257
6258fn asmExpr(
6259 gz: *GenZir,
6260 scope: *Scope,
6261 rl: ResultLoc,
6262 node: ast.Node.Index,
6263 full: ast.full.Asm,
6264) InnerError!Zir.Inst.Ref {
6265 const astgen = gz.astgen;
6266 const arena = astgen.arena;
6267 const tree = astgen.tree;
6268 const main_tokens = tree.nodes.items(.main_token);
6269 const node_datas = tree.nodes.items(.data);
6270 const token_tags = tree.tokens.items(.tag);
6271
6272 const asm_source = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, full.ast.template);
6273
6274 // See https://github.com/ziglang/zig/issues/215 and related issues discussing
6275 // possible inline assembly improvements. Until then here is status quo AstGen
6276 // for assembly syntax. It's used by std lib crypto aesni.zig.
6277
6278 if (full.outputs.len > 32) {
6279 return astgen.failNode(full.outputs[32], "too many asm outputs", .{});
6280 }
6281 var outputs_buffer: [32]Zir.Inst.Asm.Output = undefined;
6282 const outputs = outputs_buffer[0..full.outputs.len];
6283
6284 var output_type_bits: u32 = 0;
6285
6286 for (full.outputs) |output_node, i| {
6287 const symbolic_name = main_tokens[output_node];
6288 const name = try astgen.identAsString(symbolic_name);
6289 const constraint_token = symbolic_name + 2;
6290 const constraint = (try astgen.strLitAsString(constraint_token)).index;
6291 const has_arrow = token_tags[symbolic_name + 4] == .arrow;
6292 if (has_arrow) {
6293 output_type_bits |= @as(u32, 1) << @intCast(u5, i);
6294 const out_type_node = node_datas[output_node].lhs;
6295 const out_type_inst = try typeExpr(gz, scope, out_type_node);
6296 outputs[i] = .{
6297 .name = name,
6298 .constraint = constraint,
6299 .operand = out_type_inst,
6300 };
6301 } else {
6302 const ident_token = symbolic_name + 4;
6303 const str_index = try astgen.identAsString(ident_token);
6304 // TODO this needs extra code for local variables. Have a look at #215 and related
6305 // issues and decide how to handle outputs. Do we want this to be identifiers?
6306 // Or maybe we want to force this to be expressions with a pointer type.
6307 // Until that is figured out this is only hooked up for referencing Decls.
6308 const operand = try gz.addStrTok(.decl_ref, str_index, ident_token);
6309 outputs[i] = .{
6310 .name = name,
6311 .constraint = constraint,
6312 .operand = operand,
6313 };
6314 }
6315 }
6316
6317 if (full.inputs.len > 32) {
6318 return astgen.failNode(full.inputs[32], "too many asm inputs", .{});
6319 }
6320 var inputs_buffer: [32]Zir.Inst.Asm.Input = undefined;
6321 const inputs = inputs_buffer[0..full.inputs.len];
6322
6323 for (full.inputs) |input_node, i| {
6324 const symbolic_name = main_tokens[input_node];
6325 const name = try astgen.identAsString(symbolic_name);
6326 const constraint_token = symbolic_name + 2;
6327 const constraint = (try astgen.strLitAsString(constraint_token)).index;
6328 const has_arrow = token_tags[symbolic_name + 4] == .arrow;
6329 const operand = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[input_node].lhs);
6330 inputs[i] = .{
6331 .name = name,
6332 .constraint = constraint,
6333 .operand = operand,
6334 };
6335 }
6336
6337 var clobbers_buffer: [32]u32 = undefined;
6338 var clobber_i: usize = 0;
6339 if (full.first_clobber) |first_clobber| clobbers: {
6340 // asm ("foo" ::: "a", "b")
6341 // asm ("foo" ::: "a", "b",)
6342 var tok_i = first_clobber;
6343 while (true) : (tok_i += 1) {
6344 if (clobber_i >= clobbers_buffer.len) {
6345 return astgen.failTok(tok_i, "too many asm clobbers", .{});
6346 }
6347 clobbers_buffer[clobber_i] = (try astgen.strLitAsString(tok_i)).index;
6348 clobber_i += 1;
6349 tok_i += 1;
6350 switch (token_tags[tok_i]) {
6351 .r_paren => break :clobbers,
6352 .comma => {
6353 if (token_tags[tok_i + 1] == .r_paren) {
6354 break :clobbers;
6355 } else {
6356 continue;
6357 }
6358 },
6359 else => unreachable,
6360 }
6361 }
6362 }
6363
6364 const result = try gz.addAsm(.{
6365 .node = node,
6366 .asm_source = asm_source,
6367 .is_volatile = full.volatile_token != null,
6368 .output_type_bits = output_type_bits,
6369 .outputs = outputs,
6370 .inputs = inputs,
6371 .clobbers = clobbers_buffer[0..clobber_i],
6372 });
6373 return rvalue(gz, scope, rl, result, node);
6374}
6375
6376fn as(
6377 gz: *GenZir,
6378 scope: *Scope,
6379 rl: ResultLoc,
6380 node: ast.Node.Index,
6381 lhs: ast.Node.Index,
6382 rhs: ast.Node.Index,
6383) InnerError!Zir.Inst.Ref {
6384 const dest_type = try typeExpr(gz, scope, lhs);
6385 switch (rl) {
6386 .none, .none_or_ref, .discard, .ref, .ty => {
6387 const result = try expr(gz, scope, .{ .ty = dest_type }, rhs);
6388 return rvalue(gz, scope, rl, result, node);
6389 },
6390 .ptr, .inferred_ptr => |result_ptr| {
6391 return asRlPtr(gz, scope, rl, result_ptr, rhs, dest_type);
6392 },
6393 .block_ptr => |block_scope| {
6394 return asRlPtr(gz, scope, rl, block_scope.rl_ptr, rhs, dest_type);
6395 },
6396 }
6397}
6398
6399fn unionInit(
6400 gz: *GenZir,
6401 scope: *Scope,
6402 rl: ResultLoc,
6403 node: ast.Node.Index,
6404 params: []const ast.Node.Index,
6405) InnerError!Zir.Inst.Ref {
6406 const union_type = try typeExpr(gz, scope, params[0]);
6407 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
6408 switch (rl) {
6409 .none, .none_or_ref, .discard, .ref, .ty, .inferred_ptr => {
6410 const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{
6411 .container_type = union_type,
6412 .field_name = field_name,
6413 });
6414 const result = try expr(gz, scope, .{ .ty = union_type }, params[2]);
6415 return rvalue(gz, scope, rl, result, node);
6416 },
6417 .ptr => |result_ptr| {
6418 return unionInitRlPtr(gz, scope, rl, node, result_ptr, params[2], union_type, field_name);
6419 },
6420 .block_ptr => |block_scope| {
6421 return unionInitRlPtr(gz, scope, rl, node, block_scope.rl_ptr, params[2], union_type, field_name);
6422 },
6423 }
6424}
6425
6426fn unionInitRlPtr(
6427 parent_gz: *GenZir,
6428 scope: *Scope,
6429 rl: ResultLoc,
6430 node: ast.Node.Index,
6431 result_ptr: Zir.Inst.Ref,
6432 expr_node: ast.Node.Index,
6433 union_type: Zir.Inst.Ref,
6434 field_name: Zir.Inst.Ref,
6435) InnerError!Zir.Inst.Ref {
6436 const union_init_ptr = try parent_gz.addPlNode(.union_init_ptr, node, Zir.Inst.UnionInitPtr{
6437 .result_ptr = result_ptr,
6438 .union_type = union_type,
6439 .field_name = field_name,
6440 });
6441 // TODO check if we need to do the elision like below in asRlPtr
6442 return expr(parent_gz, scope, .{ .ptr = union_init_ptr }, expr_node);
6443}
6444
6445fn asRlPtr(
6446 parent_gz: *GenZir,
6447 scope: *Scope,
6448 rl: ResultLoc,
6449 result_ptr: Zir.Inst.Ref,
6450 operand_node: ast.Node.Index,
6451 dest_type: Zir.Inst.Ref,
6452) InnerError!Zir.Inst.Ref {
6453 // Detect whether this expr() call goes into rvalue() to store the result into the
6454 // result location. If it does, elide the coerce_result_ptr instruction
6455 // as well as the store instruction, instead passing the result as an rvalue.
6456 const astgen = parent_gz.astgen;
6457
6458 var as_scope = parent_gz.makeSubBlock(scope);
6459 defer as_scope.instructions.deinit(astgen.gpa);
6460
6461 as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr);
6462 const result = try expr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node);
6463 const parent_zir = &parent_gz.instructions;
6464 if (as_scope.rvalue_rl_count == 1) {
6465 // Busted! This expression didn't actually need a pointer.
6466 const zir_tags = astgen.instructions.items(.tag);
6467 const zir_datas = astgen.instructions.items(.data);
6468 try parent_zir.ensureUnusedCapacity(astgen.gpa, as_scope.instructions.items.len);
6469 for (as_scope.instructions.items) |src_inst| {
6470 if (parent_gz.indexToRef(src_inst) == as_scope.rl_ptr) continue;
6471 if (zir_tags[src_inst] == .store_to_block_ptr) {
6472 if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue;
6473 }
6474 parent_zir.appendAssumeCapacity(src_inst);
6475 }
6476 const casted_result = try parent_gz.addBin(.as, dest_type, result);
6477 return rvalue(parent_gz, scope, rl, casted_result, operand_node);
6478 } else {
6479 try parent_zir.appendSlice(astgen.gpa, as_scope.instructions.items);
6480 return result;
6481 }
6482}
6483
6484fn bitCast(
6485 gz: *GenZir,
6486 scope: *Scope,
6487 rl: ResultLoc,
6488 node: ast.Node.Index,
6489 lhs: ast.Node.Index,
6490 rhs: ast.Node.Index,
6491) InnerError!Zir.Inst.Ref {
6492 const astgen = gz.astgen;
6493 const dest_type = try typeExpr(gz, scope, lhs);
6494 switch (rl) {
6495 .none, .none_or_ref, .discard, .ty => {
6496 const operand = try expr(gz, scope, .none, rhs);
6497 const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{
6498 .lhs = dest_type,
6499 .rhs = operand,
6500 });
6501 return rvalue(gz, scope, rl, result, node);
6502 },
6503 .ref => {
6504 return astgen.failNode(node, "cannot take address of `@bitCast` result", .{});
6505 },
6506 .ptr, .inferred_ptr => |result_ptr| {
6507 return bitCastRlPtr(gz, scope, rl, node, dest_type, result_ptr, rhs);
6508 },
6509 .block_ptr => |block| {
6510 return bitCastRlPtr(gz, scope, rl, node, dest_type, block.rl_ptr, rhs);
6511 },
6512 }
6513}
6514
6515fn bitCastRlPtr(
6516 gz: *GenZir,
6517 scope: *Scope,
6518 rl: ResultLoc,
6519 node: ast.Node.Index,
6520 dest_type: Zir.Inst.Ref,
6521 result_ptr: Zir.Inst.Ref,
6522 rhs: ast.Node.Index,
6523) InnerError!Zir.Inst.Ref {
6524 const casted_result_ptr = try gz.addPlNode(.bitcast_result_ptr, node, Zir.Inst.Bin{
6525 .lhs = dest_type,
6526 .rhs = result_ptr,
6527 });
6528 return expr(gz, scope, .{ .ptr = casted_result_ptr }, rhs);
6529}
6530
6531fn typeOf(
6532 gz: *GenZir,
6533 scope: *Scope,
6534 rl: ResultLoc,
6535 node: ast.Node.Index,
6536 params: []const ast.Node.Index,
6537) InnerError!Zir.Inst.Ref {
6538 if (params.len < 1) {
6539 return gz.astgen.failNode(node, "expected at least 1 argument, found 0", .{});
6540 }
6541 if (params.len == 1) {
6542 const result = try gz.addUnNode(.typeof, try expr(gz, scope, .none, params[0]), node);
6543 return rvalue(gz, scope, rl, result, node);
6544 }
6545 const arena = gz.astgen.arena;
6546 var items = try arena.alloc(Zir.Inst.Ref, params.len);
6547 for (params) |param, param_i| {
6548 items[param_i] = try expr(gz, scope, .none, param);
6549 }
6550
6551 const result = try gz.addExtendedMultiOp(.typeof_peer, node, items);
6552 return rvalue(gz, scope, rl, result, node);
6553}
6554
6555fn builtinCall(
6556 gz: *GenZir,
6557 scope: *Scope,
6558 rl: ResultLoc,
6559 node: ast.Node.Index,
6560 params: []const ast.Node.Index,
6561) InnerError!Zir.Inst.Ref {
6562 const astgen = gz.astgen;
6563 const tree = astgen.tree;
6564 const main_tokens = tree.nodes.items(.main_token);
6565
6566 const builtin_token = main_tokens[node];
6567 const builtin_name = tree.tokenSlice(builtin_token);
6568
6569 // We handle the different builtins manually because they have different semantics depending
6570 // on the function. For example, `@as` and others participate in result location semantics,
6571 // and `@cImport` creates a special scope that collects a .c source code text buffer.
6572 // Also, some builtins have a variable number of parameters.
6573
6574 const info = BuiltinFn.list.get(builtin_name) orelse {
6575 return astgen.failNode(node, "invalid builtin function: '{s}'", .{
6576 builtin_name,
6577 });
6578 };
6579 if (info.param_count) |expected| {
6580 if (expected != params.len) {
6581 const s = if (expected == 1) "" else "s";
6582 return astgen.failNode(node, "expected {d} parameter{s}, found {d}", .{
6583 expected, s, params.len,
6584 });
6585 }
6586 }
6587
6588 // zig fmt: off
6589 switch (info.tag) {
6590 .import => {
6591 const node_tags = tree.nodes.items(.tag);
6592 const node_datas = tree.nodes.items(.data);
6593 const operand_node = params[0];
6594
6595 if (node_tags[operand_node] != .string_literal) {
6596 // Spec reference: https://github.com/ziglang/zig/issues/2206
6597 return astgen.failNode(operand_node, "@import operand must be a string literal", .{});
6598 }
6599 const str_lit_token = main_tokens[operand_node];
6600 const str = try astgen.strLitAsString(str_lit_token);
6601 try astgen.imports.put(astgen.gpa, str.index, {});
6602 const result = try gz.addStrTok(.import, str.index, str_lit_token);
6603 return rvalue(gz, scope, rl, result, node);
6604 },
6605 .compile_log => {
6606 const arg_refs = try astgen.gpa.alloc(Zir.Inst.Ref, params.len);
6607 defer astgen.gpa.free(arg_refs);
6608
6609 for (params) |param, i| arg_refs[i] = try expr(gz, scope, .none, param);
6610
6611 const result = try gz.addExtendedMultiOp(.compile_log, node, arg_refs);
6612 return rvalue(gz, scope, rl, result, node);
6613 },
6614 .field => {
6615 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
6616 if (rl == .ref) {
6617 return try gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
6618 .lhs = try expr(gz, scope, .ref, params[0]),
6619 .field_name = field_name,
6620 });
6621 }
6622 const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{
6623 .lhs = try expr(gz, scope, .none, params[0]),
6624 .field_name = field_name,
6625 });
6626 return rvalue(gz, scope, rl, result, node);
6627 },
6628 .as => return as( gz, scope, rl, node, params[0], params[1]),
6629 .bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]),
6630 .TypeOf => return typeOf( gz, scope, rl, node, params),
6631 .union_init => return unionInit(gz, scope, rl, node, params),
6632 .c_import => return cImport( gz, scope, rl, node, params[0]),
6633
6634 .@"export" => {
6635 const node_tags = tree.nodes.items(.tag);
6636 // This function causes a Decl to be exported. The first parameter is not an expression,
6637 // but an identifier of the Decl to be exported.
6638 if (node_tags[params[0]] != .identifier) {
6639 return astgen.failNode(params[0], "the first @export parameter must be an identifier", .{});
6640 }
6641 const ident_token = main_tokens[params[0]];
6642 const decl_name = try astgen.identAsString(ident_token);
6643 // TODO look for local variables in scope matching `decl_name` and emit a compile
6644 // error. Only top-level declarations can be exported. Until this is done, the
6645 // compile error will end up being "use of undeclared identifier" in Sema.
6646 const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]);
6647 _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{
6648 .decl_name = decl_name,
6649 .options = options,
6650 });
6651 return rvalue(gz, scope, rl, .void_value, node);
6652 },
6653 .@"extern" => {
6654 const type_inst = try typeExpr(gz, scope, params[0]);
6655 const options = try comptimeExpr(gz, scope, .{ .ty = .extern_options_type }, params[1]);
6656 const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{
6657 .node = gz.nodeIndexToRelative(node),
6658 .lhs = type_inst,
6659 .rhs = options,
6660 });
6661 return rvalue(gz, scope, rl, result, node);
6662 },
6663
6664 .breakpoint => return simpleNoOpVoid(gz, scope, rl, node, .breakpoint),
6665 .fence => return simpleNoOpVoid(gz, scope, rl, node, .fence),
6666
6667 .This => return rvalue(gz, scope, rl, try gz.addNodeExtended(.this, node), node),
6668 .return_address => return rvalue(gz, scope, rl, try gz.addNodeExtended(.ret_addr, node), node),
6669 .src => return rvalue(gz, scope, rl, try gz.addNodeExtended(.builtin_src, node), node),
6670 .error_return_trace => return rvalue(gz, scope, rl, try gz.addNodeExtended(.error_return_trace, node), node),
6671 .frame => return rvalue(gz, scope, rl, try gz.addNodeExtended(.frame, node), node),
6672 .frame_address => return rvalue(gz, scope, rl, try gz.addNodeExtended(.frame_address, node), node),
6673
6674 .type_info => return simpleUnOpType(gz, scope, rl, node, params[0], .type_info),
6675 .size_of => return simpleUnOpType(gz, scope, rl, node, params[0], .size_of),
6676 .bit_size_of => return simpleUnOpType(gz, scope, rl, node, params[0], .bit_size_of),
6677 .align_of => return simpleUnOpType(gz, scope, rl, node, params[0], .align_of),
6678
6679 .ptr_to_int => return simpleUnOp(gz, scope, rl, node, .none, params[0], .ptr_to_int),
6680 .error_to_int => return simpleUnOp(gz, scope, rl, node, .none, params[0], .error_to_int),
6681 .int_to_error => return simpleUnOp(gz, scope, rl, node, .{ .ty = .u16_type }, params[0], .int_to_error),
6682 .compile_error => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .compile_error),
6683 .set_eval_branch_quota => return simpleUnOp(gz, scope, rl, node, .{ .ty = .u32_type }, params[0], .set_eval_branch_quota),
6684 .enum_to_int => return simpleUnOp(gz, scope, rl, node, .none, params[0], .enum_to_int),
6685 .bool_to_int => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .bool_to_int),
6686 .embed_file => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .embed_file),
6687 .error_name => return simpleUnOp(gz, scope, rl, node, .{ .ty = .anyerror_type }, params[0], .error_name),
6688 .panic => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .panic),
6689 .set_align_stack => return simpleUnOp(gz, scope, rl, node, align_rl, params[0], .set_align_stack),
6690 .set_cold => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_cold),
6691 .set_float_mode => return simpleUnOp(gz, scope, rl, node, .{ .ty = .float_mode_type }, params[0], .set_float_mode),
6692 .set_runtime_safety => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_runtime_safety),
6693 .sqrt => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sqrt),
6694 .sin => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sin),
6695 .cos => return simpleUnOp(gz, scope, rl, node, .none, params[0], .cos),
6696 .exp => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp),
6697 .exp2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp2),
6698 .log => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log),
6699 .log2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log2),
6700 .log10 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log10),
6701 .fabs => return simpleUnOp(gz, scope, rl, node, .none, params[0], .fabs),
6702 .floor => return simpleUnOp(gz, scope, rl, node, .none, params[0], .floor),
6703 .ceil => return simpleUnOp(gz, scope, rl, node, .none, params[0], .ceil),
6704 .trunc => return simpleUnOp(gz, scope, rl, node, .none, params[0], .trunc),
6705 .round => return simpleUnOp(gz, scope, rl, node, .none, params[0], .round),
6706 .tag_name => return simpleUnOp(gz, scope, rl, node, .none, params[0], .tag_name),
6707 .Type => return simpleUnOp(gz, scope, rl, node, .none, params[0], .reify),
6708 .type_name => return simpleUnOp(gz, scope, rl, node, .none, params[0], .type_name),
6709 .Frame => return simpleUnOp(gz, scope, rl, node, .none, params[0], .frame_type),
6710 .frame_size => return simpleUnOp(gz, scope, rl, node, .none, params[0], .frame_size),
6711
6712 .float_to_int => return typeCast(gz, scope, rl, node, params[0], params[1], .float_to_int),
6713 .int_to_float => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_float),
6714 .int_to_ptr => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_ptr),
6715 .int_to_enum => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_enum),
6716 .float_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .float_cast),
6717 .int_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .int_cast),
6718 .err_set_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .err_set_cast),
6719 .ptr_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .ptr_cast),
6720 .truncate => return typeCast(gz, scope, rl, node, params[0], params[1], .truncate),
6721 .align_cast => {
6722 const dest_align = try comptimeExpr(gz, scope, align_rl, params[0]);
6723 const rhs = try expr(gz, scope, .none, params[1]);
6724 const result = try gz.addPlNode(.align_cast, node, Zir.Inst.Bin{
6725 .lhs = dest_align,
6726 .rhs = rhs,
6727 });
6728 return rvalue(gz, scope, rl, result, node);
6729 },
6730
6731 .has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl),
6732 .has_field => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_field),
6733
6734 .clz => return bitBuiltin(gz, scope, rl, node, params[0], params[1], .clz),
6735 .ctz => return bitBuiltin(gz, scope, rl, node, params[0], params[1], .ctz),
6736 .pop_count => return bitBuiltin(gz, scope, rl, node, params[0], params[1], .pop_count),
6737 .byte_swap => return bitBuiltin(gz, scope, rl, node, params[0], params[1], .byte_swap),
6738 .bit_reverse => return bitBuiltin(gz, scope, rl, node, params[0], params[1], .bit_reverse),
6739
6740 .div_exact => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_exact),
6741 .div_floor => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_floor),
6742 .div_trunc => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_trunc),
6743 .mod => return divBuiltin(gz, scope, rl, node, params[0], params[1], .mod),
6744 .rem => return divBuiltin(gz, scope, rl, node, params[0], params[1], .rem),
6745
6746 .shl_exact => return shiftOp(gz, scope, rl, node, params[0], params[1], .shl_exact),
6747 .shr_exact => return shiftOp(gz, scope, rl, node, params[0], params[1], .shr_exact),
6748
6749 .bit_offset_of => return offsetOf(gz, scope, rl, node, params[0], params[1], .bit_offset_of),
6750 .byte_offset_of => return offsetOf(gz, scope, rl, node, params[0], params[1], .byte_offset_of),
6751
6752 .c_undef => return simpleCBuiltin(gz, scope, rl, node, params[0], .c_undef),
6753 .c_include => return simpleCBuiltin(gz, scope, rl, node, params[0], .c_include),
6754
6755 .cmpxchg_strong => return cmpxchg(gz, scope, rl, node, params, .cmpxchg_strong),
6756 .cmpxchg_weak => return cmpxchg(gz, scope, rl, node, params, .cmpxchg_weak),
6757
6758 .wasm_memory_size => {
6759 const operand = try expr(gz, scope, .{ .ty = .u32_type }, params[0]);
6760 const result = try gz.addExtendedPayload(.wasm_memory_size, Zir.Inst.UnNode{
6761 .node = gz.nodeIndexToRelative(node),
6762 .operand = operand,
6763 });
6764 return rvalue(gz, scope, rl, result, node);
6765 },
6766 .wasm_memory_grow => {
6767 const index_arg = try expr(gz, scope, .{ .ty = .u32_type }, params[0]);
6768 const delta_arg = try expr(gz, scope, .{ .ty = .u32_type }, params[1]);
6769 const result = try gz.addExtendedPayload(.wasm_memory_grow, Zir.Inst.BinNode{
6770 .node = gz.nodeIndexToRelative(node),
6771 .lhs = index_arg,
6772 .rhs = delta_arg,
6773 });
6774 return rvalue(gz, scope, rl, result, node);
6775 },
6776 .c_define => {
6777 const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[0]);
6778 const value = try comptimeExpr(gz, scope, .none, params[1]);
6779 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
6780 .node = gz.nodeIndexToRelative(node),
6781 .lhs = name,
6782 .rhs = value,
6783 });
6784 return rvalue(gz, scope, rl, result, node);
6785 },
6786
6787 .splat => {
6788 const len = try expr(gz, scope, .{ .ty = .u32_type }, params[0]);
6789 const scalar = try expr(gz, scope, .none, params[1]);
6790 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
6791 .lhs = len,
6792 .rhs = scalar,
6793 });
6794 return rvalue(gz, scope, rl, result, node);
6795 },
6796 .reduce => {
6797 const op = try expr(gz, scope, .{ .ty = .reduce_op_type }, params[0]);
6798 const scalar = try expr(gz, scope, .none, params[1]);
6799 const result = try gz.addPlNode(.reduce, node, Zir.Inst.Bin{
6800 .lhs = op,
6801 .rhs = scalar,
6802 });
6803 return rvalue(gz, scope, rl, result, node);
6804 },
6805
6806 .add_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .add_with_overflow),
6807 .sub_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .sub_with_overflow),
6808 .mul_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .mul_with_overflow),
6809 .shl_with_overflow => {
6810 const int_type = try typeExpr(gz, scope, params[0]);
6811 const log2_int_type = try gz.addUnNode(.log2_int_type, int_type, params[0]);
6812 const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
6813 .ptr_type_simple = .{
6814 .is_allowzero = false,
6815 .is_mutable = true,
6816 .is_volatile = false,
6817 .size = .One,
6818 .elem_type = int_type,
6819 },
6820 } });
6821 const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]);
6822 const rhs = try expr(gz, scope, .{ .ty = log2_int_type }, params[2]);
6823 const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);
6824 const result = try gz.addExtendedPayload(.shl_with_overflow, Zir.Inst.OverflowArithmetic{
6825 .node = gz.nodeIndexToRelative(node),
6826 .lhs = lhs,
6827 .rhs = rhs,
6828 .ptr = ptr,
6829 });
6830 return rvalue(gz, scope, rl, result, node);
6831 },
6832
6833 .atomic_load => {
6834 const int_type = try typeExpr(gz, scope, params[0]);
6835 const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
6836 .ptr_type_simple = .{
6837 .is_allowzero = false,
6838 .is_mutable = false,
6839 .is_volatile = false,
6840 .size = .One,
6841 .elem_type = int_type,
6842 },
6843 } });
6844 const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]);
6845 const ordering = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[2]);
6846 const result = try gz.addPlNode(.atomic_load, node, Zir.Inst.Bin{
6847 .lhs = ptr,
6848 .rhs = ordering,
6849 });
6850 return rvalue(gz, scope, rl, result, node);
6851 },
6852 .atomic_rmw => {
6853 const int_type = try typeExpr(gz, scope, params[0]);
6854 const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
6855 .ptr_type_simple = .{
6856 .is_allowzero = false,
6857 .is_mutable = true,
6858 .is_volatile = false,
6859 .size = .One,
6860 .elem_type = int_type,
6861 },
6862 } });
6863 const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]);
6864 const operation = try expr(gz, scope, .{ .ty = .atomic_rmw_op_type }, params[2]);
6865 const operand = try expr(gz, scope, .{ .ty = int_type }, params[3]);
6866 const ordering = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[4]);
6867 const result = try gz.addPlNode(.atomic_rmw, node, Zir.Inst.AtomicRmw{
6868 .ptr = ptr,
6869 .operation = operation,
6870 .operand = operand,
6871 .ordering = ordering,
6872 });
6873 return rvalue(gz, scope, rl, result, node);
6874 },
6875 .atomic_store => {
6876 const int_type = try typeExpr(gz, scope, params[0]);
6877 const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
6878 .ptr_type_simple = .{
6879 .is_allowzero = false,
6880 .is_mutable = true,
6881 .is_volatile = false,
6882 .size = .One,
6883 .elem_type = int_type,
6884 },
6885 } });
6886 const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]);
6887 const operand = try expr(gz, scope, .{ .ty = int_type }, params[2]);
6888 const ordering = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[3]);
6889 const result = try gz.addPlNode(.atomic_store, node, Zir.Inst.AtomicStore{
6890 .ptr = ptr,
6891 .operand = operand,
6892 .ordering = ordering,
6893 });
6894 return rvalue(gz, scope, rl, result, node);
6895 },
6896 .mul_add => {
6897 const float_type = try typeExpr(gz, scope, params[0]);
6898 const mulend1 = try expr(gz, scope, .{ .ty = float_type }, params[1]);
6899 const mulend2 = try expr(gz, scope, .{ .ty = float_type }, params[2]);
6900 const addend = try expr(gz, scope, .{ .ty = float_type }, params[3]);
6901 const result = try gz.addPlNode(.mul_add, node, Zir.Inst.MulAdd{
6902 .mulend1 = mulend1,
6903 .mulend2 = mulend2,
6904 .addend = addend,
6905 });
6906 return rvalue(gz, scope, rl, result, node);
6907 },
6908 .call => {
6909 const options = try comptimeExpr(gz, scope, .{ .ty = .call_options_type }, params[0]);
6910 const callee = try expr(gz, scope, .none, params[1]);
6911 const args = try expr(gz, scope, .none, params[2]);
6912 const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{
6913 .options = options,
6914 .callee = callee,
6915 .args = args,
6916 });
6917 return rvalue(gz, scope, rl, result, node);
6918 },
6919 .field_parent_ptr => {
6920 const parent_type = try typeExpr(gz, scope, params[0]);
6921 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
6922 const field_ptr_type = try gz.addBin(.field_ptr_type, parent_type, field_name);
6923 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{
6924 .parent_type = parent_type,
6925 .field_name = field_name,
6926 .field_ptr = try expr(gz, scope, .{ .ty = field_ptr_type }, params[2]),
6927 });
6928 return rvalue(gz, scope, rl, result, node);
6929 },
6930 .memcpy => {
6931 const result = try gz.addPlNode(.memcpy, node, Zir.Inst.Memcpy{
6932 .dest = try expr(gz, scope, .{ .ty = .manyptr_u8_type }, params[0]),
6933 .source = try expr(gz, scope, .{ .ty = .manyptr_const_u8_type }, params[1]),
6934 .byte_count = try expr(gz, scope, .{ .ty = .usize_type }, params[2]),
6935 });
6936 return rvalue(gz, scope, rl, result, node);
6937 },
6938 .memset => {
6939 const result = try gz.addPlNode(.memset, node, Zir.Inst.Memset{
6940 .dest = try expr(gz, scope, .{ .ty = .manyptr_u8_type }, params[0]),
6941 .byte = try expr(gz, scope, .{ .ty = .u8_type }, params[1]),
6942 .byte_count = try expr(gz, scope, .{ .ty = .usize_type }, params[2]),
6943 });
6944 return rvalue(gz, scope, rl, result, node);
6945 },
6946 .shuffle => {
6947 const result = try gz.addPlNode(.shuffle, node, Zir.Inst.Shuffle{
6948 .elem_type = try typeExpr(gz, scope, params[0]),
6949 .a = try expr(gz, scope, .none, params[1]),
6950 .b = try expr(gz, scope, .none, params[2]),
6951 .mask = try comptimeExpr(gz, scope, .none, params[3]),
6952 });
6953 return rvalue(gz, scope, rl, result, node);
6954 },
6955 .async_call => {
6956 const result = try gz.addPlNode(.builtin_async_call, node, Zir.Inst.AsyncCall{
6957 .frame_buffer = try expr(gz, scope, .none, params[0]),
6958 .result_ptr = try expr(gz, scope, .none, params[1]),
6959 .fn_ptr = try expr(gz, scope, .none, params[2]),
6960 .args = try expr(gz, scope, .none, params[3]),
6961 });
6962 return rvalue(gz, scope, rl, result, node);
6963 },
6964 .Vector => {
6965 const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{
6966 .lhs = try comptimeExpr(gz, scope, .{.ty = .u32_type}, params[0]),
6967 .rhs = try typeExpr(gz, scope, params[1]),
6968 });
6969 return rvalue(gz, scope, rl, result, node);
6970 },
6971
6972 }
6973 // zig fmt: on
6974}
6975
6976fn simpleNoOpVoid(
6977 gz: *GenZir,
6978 scope: *Scope,
6979 rl: ResultLoc,
6980 node: ast.Node.Index,
6981 tag: Zir.Inst.Tag,
6982) InnerError!Zir.Inst.Ref {
6983 _ = try gz.addNode(tag, node);
6984 return rvalue(gz, scope, rl, .void_value, node);
6985}
6986
6987fn hasDeclOrField(
6988 gz: *GenZir,
6989 scope: *Scope,
6990 rl: ResultLoc,
6991 node: ast.Node.Index,
6992 lhs_node: ast.Node.Index,
6993 rhs_node: ast.Node.Index,
6994 tag: Zir.Inst.Tag,
6995) InnerError!Zir.Inst.Ref {
6996 const container_type = try typeExpr(gz, scope, lhs_node);
6997 const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, rhs_node);
6998 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
6999 .lhs = container_type,
7000 .rhs = name,
7001 });
7002 return rvalue(gz, scope, rl, result, node);
7003}
7004
7005fn typeCast(
7006 gz: *GenZir,
7007 scope: *Scope,
7008 rl: ResultLoc,
7009 node: ast.Node.Index,
7010 lhs_node: ast.Node.Index,
7011 rhs_node: ast.Node.Index,
7012 tag: Zir.Inst.Tag,
7013) InnerError!Zir.Inst.Ref {
7014 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
7015 .lhs = try typeExpr(gz, scope, lhs_node),
7016 .rhs = try expr(gz, scope, .none, rhs_node),
7017 });
7018 return rvalue(gz, scope, rl, result, node);
7019}
7020
7021fn simpleUnOpType(
7022 gz: *GenZir,
7023 scope: *Scope,
7024 rl: ResultLoc,
7025 node: ast.Node.Index,
7026 operand_node: ast.Node.Index,
7027 tag: Zir.Inst.Tag,
7028) InnerError!Zir.Inst.Ref {
7029 const operand = try typeExpr(gz, scope, operand_node);
7030 const result = try gz.addUnNode(tag, operand, node);
7031 return rvalue(gz, scope, rl, result, node);
7032}
7033
7034fn simpleUnOp(
7035 gz: *GenZir,
7036 scope: *Scope,
7037 rl: ResultLoc,
7038 node: ast.Node.Index,
7039 operand_rl: ResultLoc,
7040 operand_node: ast.Node.Index,
7041 tag: Zir.Inst.Tag,
7042) InnerError!Zir.Inst.Ref {
7043 const operand = try expr(gz, scope, operand_rl, operand_node);
7044 const result = try gz.addUnNode(tag, operand, node);
7045 return rvalue(gz, scope, rl, result, node);
7046}
7047
7048fn cmpxchg(
7049 gz: *GenZir,
7050 scope: *Scope,
7051 rl: ResultLoc,
7052 node: ast.Node.Index,
7053 params: []const ast.Node.Index,
7054 tag: Zir.Inst.Tag,
7055) InnerError!Zir.Inst.Ref {
7056 const int_type = try typeExpr(gz, scope, params[0]);
7057 const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
7058 .ptr_type_simple = .{
7059 .is_allowzero = false,
7060 .is_mutable = true,
7061 .is_volatile = false,
7062 .size = .One,
7063 .elem_type = int_type,
7064 },
7065 } });
7066 const result = try gz.addPlNode(tag, node, Zir.Inst.Cmpxchg{
7067 // zig fmt: off
7068 .ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]),
7069 .expected_value = try expr(gz, scope, .{ .ty = int_type }, params[2]),
7070 .new_value = try expr(gz, scope, .{ .ty = int_type }, params[3]),
7071 .success_order = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[4]),
7072 .fail_order = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[5]),
7073 // zig fmt: on
7074 });
7075 return rvalue(gz, scope, rl, result, node);
7076}
7077
7078fn bitBuiltin(
7079 gz: *GenZir,
7080 scope: *Scope,
7081 rl: ResultLoc,
7082 node: ast.Node.Index,
7083 int_type_node: ast.Node.Index,
7084 operand_node: ast.Node.Index,
7085 tag: Zir.Inst.Tag,
7086) InnerError!Zir.Inst.Ref {
7087 const int_type = try typeExpr(gz, scope, int_type_node);
7088 const operand = try expr(gz, scope, .{ .ty = int_type }, operand_node);
7089 const result = try gz.addUnNode(tag, operand, node);
7090 return rvalue(gz, scope, rl, result, node);
7091}
7092
7093fn divBuiltin(
7094 gz: *GenZir,
7095 scope: *Scope,
7096 rl: ResultLoc,
7097 node: ast.Node.Index,
7098 lhs_node: ast.Node.Index,
7099 rhs_node: ast.Node.Index,
7100 tag: Zir.Inst.Tag,
7101) InnerError!Zir.Inst.Ref {
7102 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
7103 .lhs = try expr(gz, scope, .none, lhs_node),
7104 .rhs = try expr(gz, scope, .none, rhs_node),
7105 });
7106 return rvalue(gz, scope, rl, result, node);
7107}
7108
7109fn simpleCBuiltin(
7110 gz: *GenZir,
7111 scope: *Scope,
7112 rl: ResultLoc,
7113 node: ast.Node.Index,
7114 operand_node: ast.Node.Index,
7115 tag: Zir.Inst.Extended,
7116) InnerError!Zir.Inst.Ref {
7117 const operand = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, operand_node);
7118 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
7119 .node = gz.nodeIndexToRelative(node),
7120 .operand = operand,
7121 });
7122 return rvalue(gz, scope, rl, .void_value, node);
7123}
7124
7125fn offsetOf(
7126 gz: *GenZir,
7127 scope: *Scope,
7128 rl: ResultLoc,
7129 node: ast.Node.Index,
7130 lhs_node: ast.Node.Index,
7131 rhs_node: ast.Node.Index,
7132 tag: Zir.Inst.Tag,
7133) InnerError!Zir.Inst.Ref {
7134 const type_inst = try typeExpr(gz, scope, lhs_node);
7135 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, rhs_node);
7136 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
7137 .lhs = type_inst,
7138 .rhs = field_name,
7139 });
7140 return rvalue(gz, scope, rl, result, node);
7141}
7142
7143fn shiftOp(
7144 gz: *GenZir,
7145 scope: *Scope,
7146 rl: ResultLoc,
7147 node: ast.Node.Index,
7148 lhs_node: ast.Node.Index,
7149 rhs_node: ast.Node.Index,
7150 tag: Zir.Inst.Tag,
7151) InnerError!Zir.Inst.Ref {
7152 const lhs = try expr(gz, scope, .none, lhs_node);
7153 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);
7154 const rhs = try expr(gz, scope, .{ .ty = log2_int_type }, rhs_node);
7155 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
7156 .lhs = lhs,
7157 .rhs = rhs,
7158 });
7159 return rvalue(gz, scope, rl, result, node);
7160}
7161
7162fn cImport(
7163 gz: *GenZir,
7164 scope: *Scope,
7165 rl: ResultLoc,
7166 node: ast.Node.Index,
7167 body_node: ast.Node.Index,
7168) InnerError!Zir.Inst.Ref {
7169 const astgen = gz.astgen;
7170 const gpa = astgen.gpa;
7171
7172 var block_scope = gz.makeSubBlock(scope);
7173 block_scope.force_comptime = true;
7174 defer block_scope.instructions.deinit(gpa);
7175
7176 const block_inst = try gz.addBlock(.c_import, node);
7177 const block_result = try expr(&block_scope, &block_scope.base, .none, body_node);
7178 if (!gz.refIsNoReturn(block_result)) {
7179 _ = try block_scope.addBreak(.break_inline, block_inst, .void_value);
7180 }
7181 try block_scope.setBlockBody(block_inst);
7182 try gz.instructions.append(gpa, block_inst);
7183
7184 return rvalue(gz, scope, rl, .void_value, node);
7185}
7186
7187fn overflowArithmetic(
7188 gz: *GenZir,
7189 scope: *Scope,
7190 rl: ResultLoc,
7191 node: ast.Node.Index,
7192 params: []const ast.Node.Index,
7193 tag: Zir.Inst.Extended,
7194) InnerError!Zir.Inst.Ref {
7195 const int_type = try typeExpr(gz, scope, params[0]);
7196 const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
7197 .ptr_type_simple = .{
7198 .is_allowzero = false,
7199 .is_mutable = true,
7200 .is_volatile = false,
7201 .size = .One,
7202 .elem_type = int_type,
7203 },
7204 } });
7205 const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]);
7206 const rhs = try expr(gz, scope, .{ .ty = int_type }, params[2]);
7207 const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);
7208 const result = try gz.addExtendedPayload(tag, Zir.Inst.OverflowArithmetic{
7209 .node = gz.nodeIndexToRelative(node),
7210 .lhs = lhs,
7211 .rhs = rhs,
7212 .ptr = ptr,
7213 });
7214 return rvalue(gz, scope, rl, result, node);
7215}
7216
7217fn callExpr(
7218 gz: *GenZir,
7219 scope: *Scope,
7220 rl: ResultLoc,
7221 node: ast.Node.Index,
7222 call: ast.full.Call,
7223) InnerError!Zir.Inst.Ref {
7224 const astgen = gz.astgen;
7225 const lhs = try expr(gz, scope, .none, call.ast.fn_expr);
7226
7227 const args = try astgen.gpa.alloc(Zir.Inst.Ref, call.ast.params.len);
7228 defer astgen.gpa.free(args);
7229
7230 for (call.ast.params) |param_node, i| {
7231 const param_type = try gz.add(.{
7232 .tag = .param_type,
7233 .data = .{ .param_type = .{
7234 .callee = lhs,
7235 .param_index = @intCast(u32, i),
7236 } },
7237 });
7238 args[i] = try expr(gz, scope, .{ .ty = param_type }, param_node);
7239 }
7240
7241 const modifier: std.builtin.CallOptions.Modifier = blk: {
7242 if (gz.force_comptime) {
7243 break :blk .compile_time;
7244 }
7245 if (call.async_token != null) {
7246 break :blk .async_kw;
7247 }
7248 if (gz.nosuspend_node != 0) {
7249 break :blk .no_async;
7250 }
7251 break :blk .auto;
7252 };
7253 const result: Zir.Inst.Ref = res: {
7254 const tag: Zir.Inst.Tag = switch (modifier) {
7255 .auto => .call,
7256 .async_kw => .call_async,
7257 .never_tail => unreachable,
7258 .never_inline => unreachable,
7259 .no_async => .call_nosuspend,
7260 .always_tail => unreachable,
7261 .always_inline => unreachable,
7262 .compile_time => .call_compile_time,
7263 };
7264 break :res try gz.addCall(tag, lhs, args, node);
7265 };
7266 return rvalue(gz, scope, rl, result, node); // TODO function call with result location
7267}
7268
7269pub const simple_types = std.ComptimeStringMap(Zir.Inst.Ref, .{
7270 .{ "anyerror", .anyerror_type },
7271 .{ "anyframe", .anyframe_type },
7272 .{ "bool", .bool_type },
7273 .{ "c_int", .c_int_type },
7274 .{ "c_long", .c_long_type },
7275 .{ "c_longdouble", .c_longdouble_type },
7276 .{ "c_longlong", .c_longlong_type },
7277 .{ "c_short", .c_short_type },
7278 .{ "c_uint", .c_uint_type },
7279 .{ "c_ulong", .c_ulong_type },
7280 .{ "c_ulonglong", .c_ulonglong_type },
7281 .{ "c_ushort", .c_ushort_type },
7282 .{ "c_void", .c_void_type },
7283 .{ "comptime_float", .comptime_float_type },
7284 .{ "comptime_int", .comptime_int_type },
7285 .{ "f128", .f128_type },
7286 .{ "f16", .f16_type },
7287 .{ "f32", .f32_type },
7288 .{ "f64", .f64_type },
7289 .{ "false", .bool_false },
7290 .{ "i16", .i16_type },
7291 .{ "i32", .i32_type },
7292 .{ "i64", .i64_type },
7293 .{ "i128", .i128_type },
7294 .{ "i8", .i8_type },
7295 .{ "isize", .isize_type },
7296 .{ "noreturn", .noreturn_type },
7297 .{ "null", .null_value },
7298 .{ "true", .bool_true },
7299 .{ "type", .type_type },
7300 .{ "u16", .u16_type },
7301 .{ "u32", .u32_type },
7302 .{ "u64", .u64_type },
7303 .{ "u128", .u128_type },
7304 .{ "u8", .u8_type },
7305 .{ "undefined", .undef },
7306 .{ "usize", .usize_type },
7307 .{ "void", .void_type },
7308});
7309
7310fn nodeMayNeedMemoryLocation(tree: *const ast.Tree, start_node: ast.Node.Index) bool {
7311 const node_tags = tree.nodes.items(.tag);
7312 const node_datas = tree.nodes.items(.data);
7313 const main_tokens = tree.nodes.items(.main_token);
7314 const token_tags = tree.tokens.items(.tag);
7315
7316 var node = start_node;
7317 while (true) {
7318 switch (node_tags[node]) {
7319 .root,
7320 .@"usingnamespace",
7321 .test_decl,
7322 .switch_case,
7323 .switch_case_one,
7324 .container_field_init,
7325 .container_field_align,
7326 .container_field,
7327 .asm_output,
7328 .asm_input,
7329 => unreachable,
7330
7331 .@"return",
7332 .@"break",
7333 .@"continue",
7334 .bit_not,
7335 .bool_not,
7336 .global_var_decl,
7337 .local_var_decl,
7338 .simple_var_decl,
7339 .aligned_var_decl,
7340 .@"defer",
7341 .@"errdefer",
7342 .address_of,
7343 .optional_type,
7344 .negation,
7345 .negation_wrap,
7346 .@"resume",
7347 .array_type,
7348 .array_type_sentinel,
7349 .ptr_type_aligned,
7350 .ptr_type_sentinel,
7351 .ptr_type,
7352 .ptr_type_bit_range,
7353 .@"suspend",
7354 .@"anytype",
7355 .fn_proto_simple,
7356 .fn_proto_multi,
7357 .fn_proto_one,
7358 .fn_proto,
7359 .fn_decl,
7360 .anyframe_type,
4440 .anyframe_literal,7361 .anyframe_literal,
4441 .integer_literal,7362 .integer_literal,
4442 .float_literal,7363 .float_literal,
...@@ -4568,140 +7489,1607 @@ fn nodeMayNeedMemoryLocation(tree: *const ast.Tree, start_node: ast.Node.Index)...@@ -4568,140 +7489,1607 @@ fn nodeMayNeedMemoryLocation(tree: *const ast.Tree, start_node: ast.Node.Index)
4568 .async_call_comma,7489 .async_call_comma,
4569 => return true,7490 => return true,
45707491
4571 .block_two,7492 .block_two,
4572 .block_two_semicolon,7493 .block_two_semicolon,
4573 .block,7494 .block,
4574 .block_semicolon,7495 .block_semicolon,
4575 => {7496 => {
4576 const lbrace = main_tokens[node];7497 const lbrace = main_tokens[node];
4577 if (token_tags[lbrace - 1] == .colon) {7498 if (token_tags[lbrace - 1] == .colon) {
4578 // Labeled blocks may need a memory location to forward7499 // Labeled blocks may need a memory location to forward
4579 // to their break statements.7500 // to their break statements.
4580 return true;7501 return true;
4581 } else {7502 } else {
4582 return false;7503 return false;
4583 }7504 }
7505 },
7506
7507 .builtin_call,
7508 .builtin_call_comma,
7509 .builtin_call_two,
7510 .builtin_call_two_comma,
7511 => {
7512 const builtin_token = main_tokens[node];
7513 const builtin_name = tree.tokenSlice(builtin_token);
7514 // If the builtin is an invalid name, we don't cause an error here; instead
7515 // let it pass, and the error will be "invalid builtin function" later.
7516 const builtin_info = BuiltinFn.list.get(builtin_name) orelse return false;
7517 return builtin_info.needs_mem_loc;
7518 },
7519 }
7520 }
7521}
7522
7523/// Applies `rl` semantics to `inst`. Expressions which do not do their own handling of
7524/// result locations must call this function on their result.
7525/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.
7526/// If the `ResultLoc` is `ty`, it will coerce the result to the type.
7527fn rvalue(
7528 gz: *GenZir,
7529 scope: *Scope,
7530 rl: ResultLoc,
7531 result: Zir.Inst.Ref,
7532 src_node: ast.Node.Index,
7533) InnerError!Zir.Inst.Ref {
7534 switch (rl) {
7535 .none, .none_or_ref => return result,
7536 .discard => {
7537 // Emit a compile error for discarding error values.
7538 _ = try gz.addUnNode(.ensure_result_non_error, result, src_node);
7539 return result;
7540 },
7541 .ref => {
7542 // We need a pointer but we have a value.
7543 const tree = gz.astgen.tree;
7544 const src_token = tree.firstToken(src_node);
7545 return gz.addUnTok(.ref, result, src_token);
7546 },
7547 .ty => |ty_inst| {
7548 // Quickly eliminate some common, unnecessary type coercion.
7549 const as_ty = @as(u64, @enumToInt(Zir.Inst.Ref.type_type)) << 32;
7550 const as_comptime_int = @as(u64, @enumToInt(Zir.Inst.Ref.comptime_int_type)) << 32;
7551 const as_bool = @as(u64, @enumToInt(Zir.Inst.Ref.bool_type)) << 32;
7552 const as_usize = @as(u64, @enumToInt(Zir.Inst.Ref.usize_type)) << 32;
7553 const as_void = @as(u64, @enumToInt(Zir.Inst.Ref.void_type)) << 32;
7554 switch ((@as(u64, @enumToInt(ty_inst)) << 32) | @as(u64, @enumToInt(result))) {
7555 as_ty | @enumToInt(Zir.Inst.Ref.u8_type),
7556 as_ty | @enumToInt(Zir.Inst.Ref.i8_type),
7557 as_ty | @enumToInt(Zir.Inst.Ref.u16_type),
7558 as_ty | @enumToInt(Zir.Inst.Ref.i16_type),
7559 as_ty | @enumToInt(Zir.Inst.Ref.u32_type),
7560 as_ty | @enumToInt(Zir.Inst.Ref.i32_type),
7561 as_ty | @enumToInt(Zir.Inst.Ref.u64_type),
7562 as_ty | @enumToInt(Zir.Inst.Ref.i64_type),
7563 as_ty | @enumToInt(Zir.Inst.Ref.usize_type),
7564 as_ty | @enumToInt(Zir.Inst.Ref.isize_type),
7565 as_ty | @enumToInt(Zir.Inst.Ref.c_short_type),
7566 as_ty | @enumToInt(Zir.Inst.Ref.c_ushort_type),
7567 as_ty | @enumToInt(Zir.Inst.Ref.c_int_type),
7568 as_ty | @enumToInt(Zir.Inst.Ref.c_uint_type),
7569 as_ty | @enumToInt(Zir.Inst.Ref.c_long_type),
7570 as_ty | @enumToInt(Zir.Inst.Ref.c_ulong_type),
7571 as_ty | @enumToInt(Zir.Inst.Ref.c_longlong_type),
7572 as_ty | @enumToInt(Zir.Inst.Ref.c_ulonglong_type),
7573 as_ty | @enumToInt(Zir.Inst.Ref.c_longdouble_type),
7574 as_ty | @enumToInt(Zir.Inst.Ref.f16_type),
7575 as_ty | @enumToInt(Zir.Inst.Ref.f32_type),
7576 as_ty | @enumToInt(Zir.Inst.Ref.f64_type),
7577 as_ty | @enumToInt(Zir.Inst.Ref.f128_type),
7578 as_ty | @enumToInt(Zir.Inst.Ref.c_void_type),
7579 as_ty | @enumToInt(Zir.Inst.Ref.bool_type),
7580 as_ty | @enumToInt(Zir.Inst.Ref.void_type),
7581 as_ty | @enumToInt(Zir.Inst.Ref.type_type),
7582 as_ty | @enumToInt(Zir.Inst.Ref.anyerror_type),
7583 as_ty | @enumToInt(Zir.Inst.Ref.comptime_int_type),
7584 as_ty | @enumToInt(Zir.Inst.Ref.comptime_float_type),
7585 as_ty | @enumToInt(Zir.Inst.Ref.noreturn_type),
7586 as_ty | @enumToInt(Zir.Inst.Ref.null_type),
7587 as_ty | @enumToInt(Zir.Inst.Ref.undefined_type),
7588 as_ty | @enumToInt(Zir.Inst.Ref.fn_noreturn_no_args_type),
7589 as_ty | @enumToInt(Zir.Inst.Ref.fn_void_no_args_type),
7590 as_ty | @enumToInt(Zir.Inst.Ref.fn_naked_noreturn_no_args_type),
7591 as_ty | @enumToInt(Zir.Inst.Ref.fn_ccc_void_no_args_type),
7592 as_ty | @enumToInt(Zir.Inst.Ref.single_const_pointer_to_comptime_int_type),
7593 as_ty | @enumToInt(Zir.Inst.Ref.const_slice_u8_type),
7594 as_ty | @enumToInt(Zir.Inst.Ref.enum_literal_type),
7595 as_comptime_int | @enumToInt(Zir.Inst.Ref.zero),
7596 as_comptime_int | @enumToInt(Zir.Inst.Ref.one),
7597 as_bool | @enumToInt(Zir.Inst.Ref.bool_true),
7598 as_bool | @enumToInt(Zir.Inst.Ref.bool_false),
7599 as_usize | @enumToInt(Zir.Inst.Ref.zero_usize),
7600 as_usize | @enumToInt(Zir.Inst.Ref.one_usize),
7601 as_void | @enumToInt(Zir.Inst.Ref.void_value),
7602 => return result, // type of result is already correct
7603
7604 // Need an explicit type coercion instruction.
7605 else => return gz.addPlNode(.as_node, src_node, Zir.Inst.As{
7606 .dest_type = ty_inst,
7607 .operand = result,
7608 }),
7609 }
7610 },
7611 .ptr => |ptr_inst| {
7612 _ = try gz.addPlNode(.store_node, src_node, Zir.Inst.Bin{
7613 .lhs = ptr_inst,
7614 .rhs = result,
7615 });
7616 return result;
7617 },
7618 .inferred_ptr => |alloc| {
7619 _ = try gz.addBin(.store_to_inferred_ptr, alloc, result);
7620 return result;
7621 },
7622 .block_ptr => |block_scope| {
7623 block_scope.rvalue_rl_count += 1;
7624 _ = try gz.addBin(.store_to_block_ptr, block_scope.rl_ptr, result);
7625 return result;
7626 },
7627 }
7628}
7629
7630/// Given an identifier token, obtain the string for it.
7631/// If the token uses @"" syntax, parses as a string, reports errors if applicable,
7632/// and allocates the result within `astgen.arena`.
7633/// Otherwise, returns a reference to the source code bytes directly.
7634/// See also `appendIdentStr` and `parseStrLit`.
7635fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError![]const u8 {
7636 const tree = astgen.tree;
7637 const token_tags = tree.tokens.items(.tag);
7638 assert(token_tags[token] == .identifier);
7639 const ident_name = tree.tokenSlice(token);
7640 if (!mem.startsWith(u8, ident_name, "@")) {
7641 return ident_name;
7642 }
7643 var buf: ArrayListUnmanaged(u8) = .{};
7644 defer buf.deinit(astgen.gpa);
7645 try astgen.parseStrLit(token, &buf, ident_name, 1);
7646 const duped = try astgen.arena.dupe(u8, buf.items);
7647 return duped;
7648}
7649
7650/// Given an identifier token, obtain the string for it (possibly parsing as a string
7651/// literal if it is @"" syntax), and append the string to `buf`.
7652/// See also `identifierTokenString` and `parseStrLit`.
7653fn appendIdentStr(
7654 astgen: *AstGen,
7655 token: ast.TokenIndex,
7656 buf: *ArrayListUnmanaged(u8),
7657) InnerError!void {
7658 const tree = astgen.tree;
7659 const token_tags = tree.tokens.items(.tag);
7660 assert(token_tags[token] == .identifier);
7661 const ident_name = tree.tokenSlice(token);
7662 if (!mem.startsWith(u8, ident_name, "@")) {
7663 return buf.appendSlice(astgen.gpa, ident_name);
7664 } else {
7665 return astgen.parseStrLit(token, buf, ident_name, 1);
7666 }
7667}
7668
7669/// Appends the result to `buf`.
7670fn parseStrLit(
7671 astgen: *AstGen,
7672 token: ast.TokenIndex,
7673 buf: *ArrayListUnmanaged(u8),
7674 bytes: []const u8,
7675 offset: u32,
7676) InnerError!void {
7677 const tree = astgen.tree;
7678 const raw_string = bytes[offset..];
7679 var buf_managed = buf.toManaged(astgen.gpa);
7680 const result = std.zig.string_literal.parseAppend(&buf_managed, raw_string);
7681 buf.* = buf_managed.toUnmanaged();
7682 switch (try result) {
7683 .success => return,
7684 .invalid_character => |bad_index| {
7685 return astgen.failOff(
7686 token,
7687 offset + @intCast(u32, bad_index),
7688 "invalid string literal character: '{c}'",
7689 .{raw_string[bad_index]},
7690 );
7691 },
7692 .expected_hex_digits => |bad_index| {
7693 return astgen.failOff(
7694 token,
7695 offset + @intCast(u32, bad_index),
7696 "expected hex digits after '\\x'",
7697 .{},
7698 );
7699 },
7700 .invalid_hex_escape => |bad_index| {
7701 return astgen.failOff(
7702 token,
7703 offset + @intCast(u32, bad_index),
7704 "invalid hex digit: '{c}'",
7705 .{raw_string[bad_index]},
7706 );
7707 },
7708 .invalid_unicode_escape => |bad_index| {
7709 return astgen.failOff(
7710 token,
7711 offset + @intCast(u32, bad_index),
7712 "invalid unicode digit: '{c}'",
7713 .{raw_string[bad_index]},
7714 );
7715 },
7716 .missing_matching_rbrace => |bad_index| {
7717 return astgen.failOff(
7718 token,
7719 offset + @intCast(u32, bad_index),
7720 "missing matching '}}' character",
7721 .{},
7722 );
7723 },
7724 .expected_unicode_digits => |bad_index| {
7725 return astgen.failOff(
7726 token,
7727 offset + @intCast(u32, bad_index),
7728 "expected unicode digits after '\\u'",
7729 .{},
7730 );
7731 },
7732 }
7733}
7734
7735fn failNode(
7736 astgen: *AstGen,
7737 node: ast.Node.Index,
7738 comptime format: []const u8,
7739 args: anytype,
7740) InnerError {
7741 return astgen.failNodeNotes(node, format, args, &[0]u32{});
7742}
7743
7744fn failNodeNotes(
7745 astgen: *AstGen,
7746 node: ast.Node.Index,
7747 comptime format: []const u8,
7748 args: anytype,
7749 notes: []const u32,
7750) InnerError {
7751 @setCold(true);
7752 const string_bytes = &astgen.string_bytes;
7753 const msg = @intCast(u32, string_bytes.items.len);
7754 {
7755 var managed = string_bytes.toManaged(astgen.gpa);
7756 defer string_bytes.* = managed.toUnmanaged();
7757 try managed.writer().print(format ++ "\x00", args);
7758 }
7759 const notes_index: u32 = if (notes.len != 0) blk: {
7760 const notes_start = astgen.extra.items.len;
7761 try astgen.extra.ensureCapacity(astgen.gpa, notes_start + 1 + notes.len);
7762 astgen.extra.appendAssumeCapacity(@intCast(u32, notes.len));
7763 astgen.extra.appendSliceAssumeCapacity(notes);
7764 break :blk @intCast(u32, notes_start);
7765 } else 0;
7766 try astgen.compile_errors.append(astgen.gpa, .{
7767 .msg = msg,
7768 .node = node,
7769 .token = 0,
7770 .byte_offset = 0,
7771 .notes = notes_index,
7772 });
7773 return error.AnalysisFail;
7774}
7775
7776fn failTok(
7777 astgen: *AstGen,
7778 token: ast.TokenIndex,
7779 comptime format: []const u8,
7780 args: anytype,
7781) InnerError {
7782 return astgen.failTokNotes(token, format, args, &[0]u32{});
7783}
7784
7785fn failTokNotes(
7786 astgen: *AstGen,
7787 token: ast.TokenIndex,
7788 comptime format: []const u8,
7789 args: anytype,
7790 notes: []const u32,
7791) InnerError {
7792 @setCold(true);
7793 const string_bytes = &astgen.string_bytes;
7794 const msg = @intCast(u32, string_bytes.items.len);
7795 {
7796 var managed = string_bytes.toManaged(astgen.gpa);
7797 defer string_bytes.* = managed.toUnmanaged();
7798 try managed.writer().print(format ++ "\x00", args);
7799 }
7800 const notes_index: u32 = if (notes.len != 0) blk: {
7801 const notes_start = astgen.extra.items.len;
7802 try astgen.extra.ensureCapacity(astgen.gpa, notes_start + 1 + notes.len);
7803 astgen.extra.appendAssumeCapacity(@intCast(u32, notes.len));
7804 astgen.extra.appendSliceAssumeCapacity(notes);
7805 break :blk @intCast(u32, notes_start);
7806 } else 0;
7807 try astgen.compile_errors.append(astgen.gpa, .{
7808 .msg = msg,
7809 .node = 0,
7810 .token = token,
7811 .byte_offset = 0,
7812 .notes = notes_index,
7813 });
7814 return error.AnalysisFail;
7815}
7816
7817/// Same as `fail`, except given an absolute byte offset.
7818fn failOff(
7819 astgen: *AstGen,
7820 token: ast.TokenIndex,
7821 byte_offset: u32,
7822 comptime format: []const u8,
7823 args: anytype,
7824) InnerError {
7825 @setCold(true);
7826 const string_bytes = &astgen.string_bytes;
7827 const msg = @intCast(u32, string_bytes.items.len);
7828 {
7829 var managed = string_bytes.toManaged(astgen.gpa);
7830 defer string_bytes.* = managed.toUnmanaged();
7831 try managed.writer().print(format ++ "\x00", args);
7832 }
7833 try astgen.compile_errors.append(astgen.gpa, .{
7834 .msg = msg,
7835 .node = 0,
7836 .token = token,
7837 .byte_offset = byte_offset,
7838 .notes = 0,
7839 });
7840 return error.AnalysisFail;
7841}
7842
7843fn errNoteTok(
7844 astgen: *AstGen,
7845 token: ast.TokenIndex,
7846 comptime format: []const u8,
7847 args: anytype,
7848) Allocator.Error!u32 {
7849 @setCold(true);
7850 const string_bytes = &astgen.string_bytes;
7851 const msg = @intCast(u32, string_bytes.items.len);
7852 {
7853 var managed = string_bytes.toManaged(astgen.gpa);
7854 defer string_bytes.* = managed.toUnmanaged();
7855 try managed.writer().print(format ++ "\x00", args);
7856 }
7857 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
7858 .msg = msg,
7859 .node = 0,
7860 .token = token,
7861 .byte_offset = 0,
7862 .notes = 0,
7863 });
7864}
7865
7866fn errNoteNode(
7867 astgen: *AstGen,
7868 node: ast.Node.Index,
7869 comptime format: []const u8,
7870 args: anytype,
7871) Allocator.Error!u32 {
7872 @setCold(true);
7873 const string_bytes = &astgen.string_bytes;
7874 const msg = @intCast(u32, string_bytes.items.len);
7875 {
7876 var managed = string_bytes.toManaged(astgen.gpa);
7877 defer string_bytes.* = managed.toUnmanaged();
7878 try managed.writer().print(format ++ "\x00", args);
7879 }
7880 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
7881 .msg = msg,
7882 .node = node,
7883 .token = 0,
7884 .byte_offset = 0,
7885 .notes = 0,
7886 });
7887}
7888
7889fn identAsString(astgen: *AstGen, ident_token: ast.TokenIndex) !u32 {
7890 const gpa = astgen.gpa;
7891 const string_bytes = &astgen.string_bytes;
7892 const str_index = @intCast(u32, string_bytes.items.len);
7893 try astgen.appendIdentStr(ident_token, string_bytes);
7894 const key = string_bytes.items[str_index..];
7895 const gop = try astgen.string_table.getOrPut(gpa, key);
7896 if (gop.found_existing) {
7897 string_bytes.shrinkRetainingCapacity(str_index);
7898 return gop.entry.value;
7899 } else {
7900 // We have to dupe the key into the arena, otherwise the memory
7901 // becomes invalidated when string_bytes gets data appended.
7902 // TODO https://github.com/ziglang/zig/issues/8528
7903 gop.entry.key = try astgen.arena.dupe(u8, key);
7904 gop.entry.value = str_index;
7905 try string_bytes.append(gpa, 0);
7906 return str_index;
7907 }
7908}
7909
7910const IndexSlice = struct { index: u32, len: u32 };
7911
7912fn strLitAsString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !IndexSlice {
7913 const gpa = astgen.gpa;
7914 const string_bytes = &astgen.string_bytes;
7915 const str_index = @intCast(u32, string_bytes.items.len);
7916 const token_bytes = astgen.tree.tokenSlice(str_lit_token);
7917 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
7918 const key = string_bytes.items[str_index..];
7919 const gop = try astgen.string_table.getOrPut(gpa, key);
7920 if (gop.found_existing) {
7921 string_bytes.shrinkRetainingCapacity(str_index);
7922 return IndexSlice{
7923 .index = gop.entry.value,
7924 .len = @intCast(u32, key.len),
7925 };
7926 } else {
7927 // We have to dupe the key into the arena, otherwise the memory
7928 // becomes invalidated when string_bytes gets data appended.
7929 // TODO https://github.com/ziglang/zig/issues/8528
7930 gop.entry.key = try astgen.arena.dupe(u8, key);
7931 gop.entry.value = str_index;
7932 // Still need a null byte because we are using the same table
7933 // to lookup null terminated strings, so if we get a match, it has to
7934 // be null terminated for that to work.
7935 try string_bytes.append(gpa, 0);
7936 return IndexSlice{
7937 .index = str_index,
7938 .len = @intCast(u32, key.len),
7939 };
7940 }
7941}
7942
7943fn testNameString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !u32 {
7944 const gpa = astgen.gpa;
7945 const string_bytes = &astgen.string_bytes;
7946 const str_index = @intCast(u32, string_bytes.items.len);
7947 const token_bytes = astgen.tree.tokenSlice(str_lit_token);
7948 try string_bytes.append(gpa, 0); // Indicates this is a test.
7949 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
7950 try string_bytes.append(gpa, 0);
7951 return str_index;
7952}
7953
7954const Scope = struct {
7955 tag: Tag,
7956
7957 fn cast(base: *Scope, comptime T: type) ?*T {
7958 if (T == Defer) {
7959 switch (base.tag) {
7960 .defer_normal, .defer_error => return @fieldParentPtr(T, "base", base),
7961 else => return null,
7962 }
7963 }
7964 if (base.tag != T.base_tag)
7965 return null;
7966
7967 return @fieldParentPtr(T, "base", base);
7968 }
7969
7970 const Tag = enum {
7971 gen_zir,
7972 local_val,
7973 local_ptr,
7974 defer_normal,
7975 defer_error,
7976 namespace,
7977 top,
7978 };
7979
7980 /// This is always a `const` local and importantly the `inst` is a value type, not a pointer.
7981 /// This structure lives as long as the AST generation of the Block
7982 /// node that contains the variable.
7983 const LocalVal = struct {
7984 const base_tag: Tag = .local_val;
7985 base: Scope = Scope{ .tag = base_tag },
7986 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
7987 parent: *Scope,
7988 gen_zir: *GenZir,
7989 inst: Zir.Inst.Ref,
7990 /// Source location of the corresponding variable declaration.
7991 token_src: ast.TokenIndex,
7992 /// String table index.
7993 name: u32,
7994 };
7995
7996 /// This could be a `const` or `var` local. It has a pointer instead of a value.
7997 /// This structure lives as long as the AST generation of the Block
7998 /// node that contains the variable.
7999 const LocalPtr = struct {
8000 const base_tag: Tag = .local_ptr;
8001 base: Scope = Scope{ .tag = base_tag },
8002 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
8003 parent: *Scope,
8004 gen_zir: *GenZir,
8005 ptr: Zir.Inst.Ref,
8006 /// Source location of the corresponding variable declaration.
8007 token_src: ast.TokenIndex,
8008 /// String table index.
8009 name: u32,
8010 };
8011
8012 const Defer = struct {
8013 base: Scope,
8014 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
8015 parent: *Scope,
8016 defer_node: ast.Node.Index,
8017 };
8018
8019 /// Represents a global scope that has any number of declarations in it.
8020 /// Each declaration has this as the parent scope.
8021 const Namespace = struct {
8022 const base_tag: Tag = .namespace;
8023 base: Scope = Scope{ .tag = base_tag },
8024
8025 parent: *Scope,
8026 /// Maps string table index to the source location of declaration,
8027 /// for the purposes of reporting name shadowing compile errors.
8028 decls: std.AutoHashMapUnmanaged(u32, ast.Node.Index) = .{},
8029 };
8030
8031 const Top = struct {
8032 const base_tag: Scope.Tag = .top;
8033 base: Scope = Scope{ .tag = base_tag },
8034 };
8035};
8036
8037/// This is a temporary structure; references to it are valid only
8038/// while constructing a `Zir`.
8039const GenZir = struct {
8040 const base_tag: Scope.Tag = .gen_zir;
8041 base: Scope = Scope{ .tag = base_tag },
8042 force_comptime: bool,
8043 /// How decls created in this scope should be named.
8044 anon_name_strategy: Zir.Inst.NameStrategy = .anon,
8045 /// The end of special indexes. `Zir.Inst.Ref` subtracts against this number to convert
8046 /// to `Zir.Inst.Index`. The default here is correct if there are 0 parameters.
8047 ref_start_index: u32 = Zir.Inst.Ref.typed_value_map.len,
8048 /// The containing decl AST node.
8049 decl_node_index: ast.Node.Index,
8050 /// The containing decl line index, absolute.
8051 decl_line: u32,
8052 parent: *Scope,
8053 /// All `GenZir` scopes for the same ZIR share this.
8054 astgen: *AstGen,
8055 /// Keeps track of the list of instructions in this scope only. Indexes
8056 /// to instructions in `astgen`.
8057 instructions: ArrayListUnmanaged(Zir.Inst.Index) = .{},
8058 label: ?Label = null,
8059 break_block: Zir.Inst.Index = 0,
8060 continue_block: Zir.Inst.Index = 0,
8061 /// Only valid when setBreakResultLoc is called.
8062 break_result_loc: AstGen.ResultLoc = undefined,
8063 /// When a block has a pointer result location, here it is.
8064 rl_ptr: Zir.Inst.Ref = .none,
8065 /// When a block has a type result location, here it is.
8066 rl_ty_inst: Zir.Inst.Ref = .none,
8067 /// Keeps track of how many branches of a block did not actually
8068 /// consume the result location. astgen uses this to figure out
8069 /// whether to rely on break instructions or writing to the result
8070 /// pointer for the result instruction.
8071 rvalue_rl_count: usize = 0,
8072 /// Keeps track of how many break instructions there are. When astgen is finished
8073 /// with a block, it can check this against rvalue_rl_count to find out whether
8074 /// the break instructions should be downgraded to break_void.
8075 break_count: usize = 0,
8076 /// Tracks `break :foo bar` instructions so they can possibly be elided later if
8077 /// the labeled block ends up not needing a result location pointer.
8078 labeled_breaks: ArrayListUnmanaged(Zir.Inst.Index) = .{},
8079 /// Tracks `store_to_block_ptr` instructions that correspond to break instructions
8080 /// so they can possibly be elided later if the labeled block ends up not needing
8081 /// a result location pointer.
8082 labeled_store_to_block_ptr_list: ArrayListUnmanaged(Zir.Inst.Index) = .{},
8083
8084 suspend_node: ast.Node.Index = 0,
8085 nosuspend_node: ast.Node.Index = 0,
8086
8087 fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir {
8088 return .{
8089 .force_comptime = gz.force_comptime,
8090 .ref_start_index = gz.ref_start_index,
8091 .decl_node_index = gz.decl_node_index,
8092 .decl_line = gz.decl_line,
8093 .parent = scope,
8094 .astgen = gz.astgen,
8095 .suspend_node = gz.suspend_node,
8096 .nosuspend_node = gz.nosuspend_node,
8097 };
8098 }
8099
8100 const Label = struct {
8101 token: ast.TokenIndex,
8102 block_inst: Zir.Inst.Index,
8103 used: bool = false,
8104 };
8105
8106 fn refIsNoReturn(gz: GenZir, inst_ref: Zir.Inst.Ref) bool {
8107 if (inst_ref == .unreachable_value) return true;
8108 if (gz.refToIndex(inst_ref)) |inst_index| {
8109 return gz.astgen.instructions.items(.tag)[inst_index].isNoReturn();
8110 }
8111 return false;
8112 }
8113
8114 fn calcLine(gz: GenZir, node: ast.Node.Index) u32 {
8115 const astgen = gz.astgen;
8116 const tree = astgen.tree;
8117 const node_tags = tree.nodes.items(.tag);
8118 const token_starts = tree.tokens.items(.start);
8119 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
8120 const node_start = token_starts[tree.firstToken(node)];
8121 const source = tree.source[decl_start..node_start];
8122 const loc = std.zig.findLineColumn(source, source.len);
8123 return @intCast(u32, gz.decl_line + loc.line);
8124 }
8125
8126 fn tokSrcLoc(gz: GenZir, token_index: ast.TokenIndex) LazySrcLoc {
8127 return .{ .token_offset = token_index - gz.srcToken() };
8128 }
8129
8130 fn nodeSrcLoc(gz: GenZir, node_index: ast.Node.Index) LazySrcLoc {
8131 return .{ .node_offset = gz.nodeIndexToRelative(node_index) };
8132 }
8133
8134 fn nodeIndexToRelative(gz: GenZir, node_index: ast.Node.Index) i32 {
8135 return @bitCast(i32, node_index) - @bitCast(i32, gz.decl_node_index);
8136 }
8137
8138 fn tokenIndexToRelative(gz: GenZir, token: ast.TokenIndex) u32 {
8139 return token - gz.srcToken();
8140 }
8141
8142 fn srcToken(gz: GenZir) ast.TokenIndex {
8143 return gz.astgen.tree.firstToken(gz.decl_node_index);
8144 }
8145
8146 fn indexToRef(gz: GenZir, inst: Zir.Inst.Index) Zir.Inst.Ref {
8147 return @intToEnum(Zir.Inst.Ref, gz.ref_start_index + inst);
8148 }
8149
8150 fn refToIndex(gz: GenZir, inst: Zir.Inst.Ref) ?Zir.Inst.Index {
8151 const ref_int = @enumToInt(inst);
8152 if (ref_int >= gz.ref_start_index) {
8153 return ref_int - gz.ref_start_index;
8154 } else {
8155 return null;
8156 }
8157 }
8158
8159 fn setBreakResultLoc(gz: *GenZir, parent_rl: AstGen.ResultLoc) void {
8160 // Depending on whether the result location is a pointer or value, different
8161 // ZIR needs to be generated. In the former case we rely on storing to the
8162 // pointer to communicate the result, and use breakvoid; in the latter case
8163 // the block break instructions will have the result values.
8164 // One more complication: when the result location is a pointer, we detect
8165 // the scenario where the result location is not consumed. In this case
8166 // we emit ZIR for the block break instructions to have the result values,
8167 // and then rvalue() on that to pass the value to the result location.
8168 switch (parent_rl) {
8169 .ty => |ty_inst| {
8170 gz.rl_ty_inst = ty_inst;
8171 gz.break_result_loc = parent_rl;
8172 },
8173 .none_or_ref => {
8174 gz.break_result_loc = .ref;
8175 },
8176 .discard, .none, .ptr, .ref => {
8177 gz.break_result_loc = parent_rl;
4584 },8178 },
45858179
4586 .builtin_call,8180 .inferred_ptr => |ptr| {
4587 .builtin_call_comma,8181 gz.rl_ptr = ptr;
4588 .builtin_call_two,8182 gz.break_result_loc = .{ .block_ptr = gz };
4589 .builtin_call_two_comma,8183 },
4590 => {8184
4591 const builtin_token = main_tokens[node];8185 .block_ptr => |parent_block_scope| {
4592 const builtin_name = tree.tokenSlice(builtin_token);8186 gz.rl_ty_inst = parent_block_scope.rl_ty_inst;
4593 // If the builtin is an invalid name, we don't cause an error here; instead8187 gz.rl_ptr = parent_block_scope.rl_ptr;
4594 // let it pass, and the error will be "invalid builtin function" later.8188 gz.break_result_loc = .{ .block_ptr = gz };
4595 const builtin_info = BuiltinFn.list.get(builtin_name) orelse return false;
4596 return builtin_info.needs_mem_loc;
4597 },8189 },
4598 }8190 }
4599 }8191 }
4600}
46018192
4602/// Applies `rl` semantics to `inst`. Expressions which do not do their own handling of8193 fn setBoolBrBody(gz: GenZir, inst: Zir.Inst.Index) !void {
4603/// result locations must call this function on their result.8194 const gpa = gz.astgen.gpa;
4604/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.8195 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
4605/// If the `ResultLoc` is `ty`, it will coerce the result to the type.8196 @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
4606fn rvalue(8197 const zir_datas = gz.astgen.instructions.items(.data);
4607 gz: *GenZir,8198 zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity(
4608 scope: *Scope,8199 Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
4609 rl: ResultLoc,8200 );
4610 result: zir.Inst.Ref,8201 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
4611 src_node: ast.Node.Index,8202 }
4612) InnerError!zir.Inst.Ref {
4613 switch (rl) {
4614 .none, .none_or_ref => return result,
4615 .discard => {
4616 // Emit a compile error for discarding error values.
4617 _ = try gz.addUnNode(.ensure_result_non_error, result, src_node);
4618 return result;
4619 },
4620 .ref => {
4621 // We need a pointer but we have a value.
4622 const tree = gz.tree();
4623 const src_token = tree.firstToken(src_node);
4624 return gz.addUnTok(.ref, result, src_token);
4625 },
4626 .ty => |ty_inst| {
4627 // Quickly eliminate some common, unnecessary type coercion.
4628 const as_ty = @as(u64, @enumToInt(zir.Inst.Ref.type_type)) << 32;
4629 const as_comptime_int = @as(u64, @enumToInt(zir.Inst.Ref.comptime_int_type)) << 32;
4630 const as_bool = @as(u64, @enumToInt(zir.Inst.Ref.bool_type)) << 32;
4631 const as_usize = @as(u64, @enumToInt(zir.Inst.Ref.usize_type)) << 32;
4632 const as_void = @as(u64, @enumToInt(zir.Inst.Ref.void_type)) << 32;
4633 switch ((@as(u64, @enumToInt(ty_inst)) << 32) | @as(u64, @enumToInt(result))) {
4634 as_ty | @enumToInt(zir.Inst.Ref.u8_type),
4635 as_ty | @enumToInt(zir.Inst.Ref.i8_type),
4636 as_ty | @enumToInt(zir.Inst.Ref.u16_type),
4637 as_ty | @enumToInt(zir.Inst.Ref.i16_type),
4638 as_ty | @enumToInt(zir.Inst.Ref.u32_type),
4639 as_ty | @enumToInt(zir.Inst.Ref.i32_type),
4640 as_ty | @enumToInt(zir.Inst.Ref.u64_type),
4641 as_ty | @enumToInt(zir.Inst.Ref.i64_type),
4642 as_ty | @enumToInt(zir.Inst.Ref.usize_type),
4643 as_ty | @enumToInt(zir.Inst.Ref.isize_type),
4644 as_ty | @enumToInt(zir.Inst.Ref.c_short_type),
4645 as_ty | @enumToInt(zir.Inst.Ref.c_ushort_type),
4646 as_ty | @enumToInt(zir.Inst.Ref.c_int_type),
4647 as_ty | @enumToInt(zir.Inst.Ref.c_uint_type),
4648 as_ty | @enumToInt(zir.Inst.Ref.c_long_type),
4649 as_ty | @enumToInt(zir.Inst.Ref.c_ulong_type),
4650 as_ty | @enumToInt(zir.Inst.Ref.c_longlong_type),
4651 as_ty | @enumToInt(zir.Inst.Ref.c_ulonglong_type),
4652 as_ty | @enumToInt(zir.Inst.Ref.c_longdouble_type),
4653 as_ty | @enumToInt(zir.Inst.Ref.f16_type),
4654 as_ty | @enumToInt(zir.Inst.Ref.f32_type),
4655 as_ty | @enumToInt(zir.Inst.Ref.f64_type),
4656 as_ty | @enumToInt(zir.Inst.Ref.f128_type),
4657 as_ty | @enumToInt(zir.Inst.Ref.c_void_type),
4658 as_ty | @enumToInt(zir.Inst.Ref.bool_type),
4659 as_ty | @enumToInt(zir.Inst.Ref.void_type),
4660 as_ty | @enumToInt(zir.Inst.Ref.type_type),
4661 as_ty | @enumToInt(zir.Inst.Ref.anyerror_type),
4662 as_ty | @enumToInt(zir.Inst.Ref.comptime_int_type),
4663 as_ty | @enumToInt(zir.Inst.Ref.comptime_float_type),
4664 as_ty | @enumToInt(zir.Inst.Ref.noreturn_type),
4665 as_ty | @enumToInt(zir.Inst.Ref.null_type),
4666 as_ty | @enumToInt(zir.Inst.Ref.undefined_type),
4667 as_ty | @enumToInt(zir.Inst.Ref.fn_noreturn_no_args_type),
4668 as_ty | @enumToInt(zir.Inst.Ref.fn_void_no_args_type),
4669 as_ty | @enumToInt(zir.Inst.Ref.fn_naked_noreturn_no_args_type),
4670 as_ty | @enumToInt(zir.Inst.Ref.fn_ccc_void_no_args_type),
4671 as_ty | @enumToInt(zir.Inst.Ref.single_const_pointer_to_comptime_int_type),
4672 as_ty | @enumToInt(zir.Inst.Ref.const_slice_u8_type),
4673 as_ty | @enumToInt(zir.Inst.Ref.enum_literal_type),
4674 as_comptime_int | @enumToInt(zir.Inst.Ref.zero),
4675 as_comptime_int | @enumToInt(zir.Inst.Ref.one),
4676 as_bool | @enumToInt(zir.Inst.Ref.bool_true),
4677 as_bool | @enumToInt(zir.Inst.Ref.bool_false),
4678 as_usize | @enumToInt(zir.Inst.Ref.zero_usize),
4679 as_usize | @enumToInt(zir.Inst.Ref.one_usize),
4680 as_void | @enumToInt(zir.Inst.Ref.void_value),
4681 => return result, // type of result is already correct
46828203
4683 // Need an explicit type coercion instruction.8204 fn setBlockBody(gz: GenZir, inst: Zir.Inst.Index) !void {
4684 else => return gz.addPlNode(.as_node, src_node, zir.Inst.As{8205 const gpa = gz.astgen.gpa;
4685 .dest_type = ty_inst,8206 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
4686 .operand = result,8207 @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
4687 }),8208 const zir_datas = gz.astgen.instructions.items(.data);
8209 zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity(
8210 Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
8211 );
8212 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
8213 }
8214
8215 /// Same as `setBlockBody` except we don't copy instructions which are
8216 /// `store_to_block_ptr` instructions with lhs set to .none.
8217 fn setBlockBodyEliding(gz: GenZir, inst: Zir.Inst.Index) !void {
8218 const gpa = gz.astgen.gpa;
8219 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
8220 @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
8221 const zir_datas = gz.astgen.instructions.items(.data);
8222 const zir_tags = gz.astgen.instructions.items(.tag);
8223 const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{
8224 .body_len = @intCast(u32, gz.instructions.items.len),
8225 });
8226 zir_datas[inst].pl_node.payload_index = block_pl_index;
8227 for (gz.instructions.items) |sub_inst| {
8228 if (zir_tags[sub_inst] == .store_to_block_ptr and
8229 zir_datas[sub_inst].bin.lhs == .none)
8230 {
8231 // Decrement `body_len`.
8232 gz.astgen.extra.items[block_pl_index] -= 1;
8233 continue;
4688 }8234 }
4689 },8235 gz.astgen.extra.appendAssumeCapacity(sub_inst);
4690 .ptr => |ptr_inst| {8236 }
4691 _ = try gz.addPlNode(.store_node, src_node, zir.Inst.Bin{8237 }
4692 .lhs = ptr_inst,8238
4693 .rhs = result,8239 fn addFunc(gz: *GenZir, args: struct {
8240 src_node: ast.Node.Index,
8241 param_types: []const Zir.Inst.Ref,
8242 body: []const Zir.Inst.Index,
8243 ret_ty: Zir.Inst.Ref,
8244 cc: Zir.Inst.Ref,
8245 align_inst: Zir.Inst.Ref,
8246 lib_name: u32,
8247 is_var_args: bool,
8248 is_inferred_error: bool,
8249 is_test: bool,
8250 is_extern: bool,
8251 }) !Zir.Inst.Ref {
8252 assert(args.src_node != 0);
8253 assert(args.ret_ty != .none);
8254 const astgen = gz.astgen;
8255 const gpa = astgen.gpa;
8256
8257 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8258 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
8259
8260 var src_locs_buffer: [3]u32 = undefined;
8261 var src_locs: []u32 = src_locs_buffer[0..0];
8262 if (args.body.len != 0) {
8263 const tree = astgen.tree;
8264 const node_tags = tree.nodes.items(.tag);
8265 const node_datas = tree.nodes.items(.data);
8266 const token_starts = tree.tokens.items(.start);
8267 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
8268 const fn_decl = args.src_node;
8269 assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl);
8270 const block = node_datas[fn_decl].rhs;
8271 const lbrace_start = token_starts[tree.firstToken(block)];
8272 const rbrace_start = token_starts[tree.lastToken(block)];
8273 const lbrace_source = tree.source[decl_start..lbrace_start];
8274 const lbrace_loc = std.zig.findLineColumn(lbrace_source, lbrace_source.len);
8275 const rbrace_source = tree.source[lbrace_start..rbrace_start];
8276 const rbrace_loc = std.zig.findLineColumn(rbrace_source, rbrace_source.len);
8277 const lbrace_line = @intCast(u32, lbrace_loc.line);
8278 const rbrace_line = lbrace_line + @intCast(u32, rbrace_loc.line);
8279 const columns = @intCast(u32, lbrace_loc.column) |
8280 (@intCast(u32, rbrace_loc.column) << 16);
8281 src_locs_buffer[0] = lbrace_line;
8282 src_locs_buffer[1] = rbrace_line;
8283 src_locs_buffer[2] = columns;
8284 src_locs = &src_locs_buffer;
8285 }
8286
8287 if (args.cc != .none or args.lib_name != 0 or
8288 args.is_var_args or args.is_test or args.align_inst != .none or
8289 args.is_extern)
8290 {
8291 try astgen.extra.ensureUnusedCapacity(
8292 gpa,
8293 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
8294 args.param_types.len + args.body.len + src_locs.len +
8295 @boolToInt(args.lib_name != 0) +
8296 @boolToInt(args.align_inst != .none) +
8297 @boolToInt(args.cc != .none),
8298 );
8299 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
8300 .src_node = gz.nodeIndexToRelative(args.src_node),
8301 .return_type = args.ret_ty,
8302 .param_types_len = @intCast(u32, args.param_types.len),
8303 .body_len = @intCast(u32, args.body.len),
4694 });8304 });
4695 return result;8305 if (args.lib_name != 0) {
4696 },8306 astgen.extra.appendAssumeCapacity(args.lib_name);
4697 .inferred_ptr => |alloc| {8307 }
4698 _ = try gz.addBin(.store_to_inferred_ptr, alloc, result);8308 if (args.cc != .none) {
4699 return result;8309 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc));
8310 }
8311 if (args.align_inst != .none) {
8312 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
8313 }
8314 astgen.appendRefsAssumeCapacity(args.param_types);
8315 astgen.extra.appendSliceAssumeCapacity(args.body);
8316 astgen.extra.appendSliceAssumeCapacity(src_locs);
8317
8318 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8319 astgen.instructions.appendAssumeCapacity(.{
8320 .tag = .extended,
8321 .data = .{ .extended = .{
8322 .opcode = .func,
8323 .small = @bitCast(u16, Zir.Inst.ExtendedFunc.Small{
8324 .is_var_args = args.is_var_args,
8325 .is_inferred_error = args.is_inferred_error,
8326 .has_lib_name = args.lib_name != 0,
8327 .has_cc = args.cc != .none,
8328 .has_align = args.align_inst != .none,
8329 .is_test = args.is_test,
8330 .is_extern = args.is_extern,
8331 }),
8332 .operand = payload_index,
8333 } },
8334 });
8335 gz.instructions.appendAssumeCapacity(new_index);
8336 return gz.indexToRef(new_index);
8337 } else {
8338 try gz.astgen.extra.ensureUnusedCapacity(
8339 gpa,
8340 @typeInfo(Zir.Inst.Func).Struct.fields.len +
8341 args.param_types.len + args.body.len + src_locs.len,
8342 );
8343
8344 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{
8345 .return_type = args.ret_ty,
8346 .param_types_len = @intCast(u32, args.param_types.len),
8347 .body_len = @intCast(u32, args.body.len),
8348 });
8349 gz.astgen.appendRefsAssumeCapacity(args.param_types);
8350 gz.astgen.extra.appendSliceAssumeCapacity(args.body);
8351 gz.astgen.extra.appendSliceAssumeCapacity(src_locs);
8352
8353 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;
8354 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8355 gz.astgen.instructions.appendAssumeCapacity(.{
8356 .tag = tag,
8357 .data = .{ .pl_node = .{
8358 .src_node = gz.nodeIndexToRelative(args.src_node),
8359 .payload_index = payload_index,
8360 } },
8361 });
8362 gz.instructions.appendAssumeCapacity(new_index);
8363 return gz.indexToRef(new_index);
8364 }
8365 }
8366
8367 fn addVar(gz: *GenZir, args: struct {
8368 align_inst: Zir.Inst.Ref,
8369 lib_name: u32,
8370 var_type: Zir.Inst.Ref,
8371 init: Zir.Inst.Ref,
8372 is_extern: bool,
8373 is_threadlocal: bool,
8374 }) !Zir.Inst.Ref {
8375 const astgen = gz.astgen;
8376 const gpa = astgen.gpa;
8377
8378 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8379 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
8380
8381 try astgen.extra.ensureUnusedCapacity(
8382 gpa,
8383 @typeInfo(Zir.Inst.ExtendedVar).Struct.fields.len +
8384 @boolToInt(args.lib_name != 0) +
8385 @boolToInt(args.align_inst != .none) +
8386 @boolToInt(args.init != .none),
8387 );
8388 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedVar{
8389 .var_type = args.var_type,
8390 });
8391 if (args.lib_name != 0) {
8392 astgen.extra.appendAssumeCapacity(args.lib_name);
8393 }
8394 if (args.align_inst != .none) {
8395 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
8396 }
8397 if (args.init != .none) {
8398 astgen.extra.appendAssumeCapacity(@enumToInt(args.init));
8399 }
8400
8401 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8402 astgen.instructions.appendAssumeCapacity(.{
8403 .tag = .extended,
8404 .data = .{ .extended = .{
8405 .opcode = .variable,
8406 .small = @bitCast(u16, Zir.Inst.ExtendedVar.Small{
8407 .has_lib_name = args.lib_name != 0,
8408 .has_align = args.align_inst != .none,
8409 .has_init = args.init != .none,
8410 .is_extern = args.is_extern,
8411 .is_threadlocal = args.is_threadlocal,
8412 }),
8413 .operand = payload_index,
8414 } },
8415 });
8416 gz.instructions.appendAssumeCapacity(new_index);
8417 return gz.indexToRef(new_index);
8418 }
8419
8420 fn addCall(
8421 gz: *GenZir,
8422 tag: Zir.Inst.Tag,
8423 callee: Zir.Inst.Ref,
8424 args: []const Zir.Inst.Ref,
8425 /// Absolute node index. This function does the conversion to offset from Decl.
8426 src_node: ast.Node.Index,
8427 ) !Zir.Inst.Ref {
8428 assert(callee != .none);
8429 assert(src_node != 0);
8430 const gpa = gz.astgen.gpa;
8431 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8432 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8433 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
8434 @typeInfo(Zir.Inst.Call).Struct.fields.len + args.len);
8435
8436 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Call{
8437 .callee = callee,
8438 .args_len = @intCast(u32, args.len),
8439 });
8440 gz.astgen.appendRefsAssumeCapacity(args);
8441
8442 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8443 gz.astgen.instructions.appendAssumeCapacity(.{
8444 .tag = tag,
8445 .data = .{ .pl_node = .{
8446 .src_node = gz.nodeIndexToRelative(src_node),
8447 .payload_index = payload_index,
8448 } },
8449 });
8450 gz.instructions.appendAssumeCapacity(new_index);
8451 return gz.indexToRef(new_index);
8452 }
8453
8454 /// Note that this returns a `Zir.Inst.Index` not a ref.
8455 /// Leaves the `payload_index` field undefined.
8456 fn addBoolBr(
8457 gz: *GenZir,
8458 tag: Zir.Inst.Tag,
8459 lhs: Zir.Inst.Ref,
8460 ) !Zir.Inst.Index {
8461 assert(lhs != .none);
8462 const gpa = gz.astgen.gpa;
8463 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8464 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8465
8466 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8467 gz.astgen.instructions.appendAssumeCapacity(.{
8468 .tag = tag,
8469 .data = .{ .bool_br = .{
8470 .lhs = lhs,
8471 .payload_index = undefined,
8472 } },
8473 });
8474 gz.instructions.appendAssumeCapacity(new_index);
8475 return new_index;
8476 }
8477
8478 fn addInt(gz: *GenZir, integer: u64) !Zir.Inst.Ref {
8479 return gz.add(.{
8480 .tag = .int,
8481 .data = .{ .int = integer },
8482 });
8483 }
8484
8485 fn addIntBig(gz: *GenZir, limbs: []const std.math.big.Limb) !Zir.Inst.Ref {
8486 const astgen = gz.astgen;
8487 const gpa = astgen.gpa;
8488 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8489 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
8490 try astgen.string_bytes.ensureUnusedCapacity(gpa, @sizeOf(std.math.big.Limb) * limbs.len);
8491
8492 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8493 astgen.instructions.appendAssumeCapacity(.{
8494 .tag = .int_big,
8495 .data = .{ .str = .{
8496 .start = @intCast(u32, astgen.string_bytes.items.len),
8497 .len = @intCast(u32, limbs.len),
8498 } },
8499 });
8500 gz.instructions.appendAssumeCapacity(new_index);
8501 astgen.string_bytes.appendSliceAssumeCapacity(mem.sliceAsBytes(limbs));
8502 return gz.indexToRef(new_index);
8503 }
8504
8505 fn addFloat(gz: *GenZir, number: f32, src_node: ast.Node.Index) !Zir.Inst.Ref {
8506 return gz.add(.{
8507 .tag = .float,
8508 .data = .{ .float = .{
8509 .src_node = gz.nodeIndexToRelative(src_node),
8510 .number = number,
8511 } },
8512 });
8513 }
8514
8515 fn addUnNode(
8516 gz: *GenZir,
8517 tag: Zir.Inst.Tag,
8518 operand: Zir.Inst.Ref,
8519 /// Absolute node index. This function does the conversion to offset from Decl.
8520 src_node: ast.Node.Index,
8521 ) !Zir.Inst.Ref {
8522 assert(operand != .none);
8523 return gz.add(.{
8524 .tag = tag,
8525 .data = .{ .un_node = .{
8526 .operand = operand,
8527 .src_node = gz.nodeIndexToRelative(src_node),
8528 } },
8529 });
8530 }
8531
8532 fn addPlNode(
8533 gz: *GenZir,
8534 tag: Zir.Inst.Tag,
8535 /// Absolute node index. This function does the conversion to offset from Decl.
8536 src_node: ast.Node.Index,
8537 extra: anytype,
8538 ) !Zir.Inst.Ref {
8539 const gpa = gz.astgen.gpa;
8540 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8541 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8542
8543 const payload_index = try gz.astgen.addExtra(extra);
8544 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8545 gz.astgen.instructions.appendAssumeCapacity(.{
8546 .tag = tag,
8547 .data = .{ .pl_node = .{
8548 .src_node = gz.nodeIndexToRelative(src_node),
8549 .payload_index = payload_index,
8550 } },
8551 });
8552 gz.instructions.appendAssumeCapacity(new_index);
8553 return gz.indexToRef(new_index);
8554 }
8555
8556 fn addExtendedPayload(
8557 gz: *GenZir,
8558 opcode: Zir.Inst.Extended,
8559 extra: anytype,
8560 ) !Zir.Inst.Ref {
8561 const gpa = gz.astgen.gpa;
8562
8563 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8564 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8565
8566 const payload_index = try gz.astgen.addExtra(extra);
8567 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8568 gz.astgen.instructions.appendAssumeCapacity(.{
8569 .tag = .extended,
8570 .data = .{ .extended = .{
8571 .opcode = opcode,
8572 .small = undefined,
8573 .operand = payload_index,
8574 } },
8575 });
8576 gz.instructions.appendAssumeCapacity(new_index);
8577 return gz.indexToRef(new_index);
8578 }
8579
8580 fn addExtendedMultiOp(
8581 gz: *GenZir,
8582 opcode: Zir.Inst.Extended,
8583 node: ast.Node.Index,
8584 operands: []const Zir.Inst.Ref,
8585 ) !Zir.Inst.Ref {
8586 const astgen = gz.astgen;
8587 const gpa = astgen.gpa;
8588
8589 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8590 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
8591 try astgen.extra.ensureUnusedCapacity(
8592 gpa,
8593 @typeInfo(Zir.Inst.NodeMultiOp).Struct.fields.len + operands.len,
8594 );
8595
8596 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.NodeMultiOp{
8597 .src_node = gz.nodeIndexToRelative(node),
8598 });
8599 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8600 astgen.instructions.appendAssumeCapacity(.{
8601 .tag = .extended,
8602 .data = .{ .extended = .{
8603 .opcode = opcode,
8604 .small = @intCast(u16, operands.len),
8605 .operand = payload_index,
8606 } },
8607 });
8608 gz.instructions.appendAssumeCapacity(new_index);
8609 astgen.appendRefsAssumeCapacity(operands);
8610 return gz.indexToRef(new_index);
8611 }
8612
8613 fn addArrayTypeSentinel(
8614 gz: *GenZir,
8615 len: Zir.Inst.Ref,
8616 sentinel: Zir.Inst.Ref,
8617 elem_type: Zir.Inst.Ref,
8618 ) !Zir.Inst.Ref {
8619 const gpa = gz.astgen.gpa;
8620 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8621 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8622
8623 const payload_index = try gz.astgen.addExtra(Zir.Inst.ArrayTypeSentinel{
8624 .sentinel = sentinel,
8625 .elem_type = elem_type,
8626 });
8627 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8628 gz.astgen.instructions.appendAssumeCapacity(.{
8629 .tag = .array_type_sentinel,
8630 .data = .{ .array_type_sentinel = .{
8631 .len = len,
8632 .payload_index = payload_index,
8633 } },
8634 });
8635 gz.instructions.appendAssumeCapacity(new_index);
8636 return gz.indexToRef(new_index);
8637 }
8638
8639 fn addUnTok(
8640 gz: *GenZir,
8641 tag: Zir.Inst.Tag,
8642 operand: Zir.Inst.Ref,
8643 /// Absolute token index. This function does the conversion to Decl offset.
8644 abs_tok_index: ast.TokenIndex,
8645 ) !Zir.Inst.Ref {
8646 assert(operand != .none);
8647 return gz.add(.{
8648 .tag = tag,
8649 .data = .{ .un_tok = .{
8650 .operand = operand,
8651 .src_tok = gz.tokenIndexToRelative(abs_tok_index),
8652 } },
8653 });
8654 }
8655
8656 fn addStrTok(
8657 gz: *GenZir,
8658 tag: Zir.Inst.Tag,
8659 str_index: u32,
8660 /// Absolute token index. This function does the conversion to Decl offset.
8661 abs_tok_index: ast.TokenIndex,
8662 ) !Zir.Inst.Ref {
8663 return gz.add(.{
8664 .tag = tag,
8665 .data = .{ .str_tok = .{
8666 .start = str_index,
8667 .src_tok = gz.tokenIndexToRelative(abs_tok_index),
8668 } },
8669 });
8670 }
8671
8672 fn addBreak(
8673 gz: *GenZir,
8674 tag: Zir.Inst.Tag,
8675 break_block: Zir.Inst.Index,
8676 operand: Zir.Inst.Ref,
8677 ) !Zir.Inst.Index {
8678 return gz.addAsIndex(.{
8679 .tag = tag,
8680 .data = .{ .@"break" = .{
8681 .block_inst = break_block,
8682 .operand = operand,
8683 } },
8684 });
8685 }
8686
8687 fn addBin(
8688 gz: *GenZir,
8689 tag: Zir.Inst.Tag,
8690 lhs: Zir.Inst.Ref,
8691 rhs: Zir.Inst.Ref,
8692 ) !Zir.Inst.Ref {
8693 assert(lhs != .none);
8694 assert(rhs != .none);
8695 return gz.add(.{
8696 .tag = tag,
8697 .data = .{ .bin = .{
8698 .lhs = lhs,
8699 .rhs = rhs,
8700 } },
8701 });
8702 }
8703
8704 fn addDecl(
8705 gz: *GenZir,
8706 tag: Zir.Inst.Tag,
8707 decl_index: u32,
8708 src_node: ast.Node.Index,
8709 ) !Zir.Inst.Ref {
8710 return gz.add(.{
8711 .tag = tag,
8712 .data = .{ .pl_node = .{
8713 .src_node = gz.nodeIndexToRelative(src_node),
8714 .payload_index = decl_index,
8715 } },
8716 });
8717 }
8718
8719 fn addNode(
8720 gz: *GenZir,
8721 tag: Zir.Inst.Tag,
8722 /// Absolute node index. This function does the conversion to offset from Decl.
8723 src_node: ast.Node.Index,
8724 ) !Zir.Inst.Ref {
8725 return gz.add(.{
8726 .tag = tag,
8727 .data = .{ .node = gz.nodeIndexToRelative(src_node) },
8728 });
8729 }
8730
8731 fn addNodeExtended(
8732 gz: *GenZir,
8733 opcode: Zir.Inst.Extended,
8734 /// Absolute node index. This function does the conversion to offset from Decl.
8735 src_node: ast.Node.Index,
8736 ) !Zir.Inst.Ref {
8737 return gz.add(.{
8738 .tag = .extended,
8739 .data = .{ .extended = .{
8740 .opcode = opcode,
8741 .small = undefined,
8742 .operand = @bitCast(u32, gz.nodeIndexToRelative(src_node)),
8743 } },
8744 });
8745 }
8746
8747 fn addAllocExtended(
8748 gz: *GenZir,
8749 args: struct {
8750 /// Absolute node index. This function does the conversion to offset from Decl.
8751 node: ast.Node.Index,
8752 type_inst: Zir.Inst.Ref,
8753 align_inst: Zir.Inst.Ref,
8754 is_const: bool,
8755 is_comptime: bool,
4700 },8756 },
4701 .block_ptr => |block_scope| {8757 ) !Zir.Inst.Ref {
4702 block_scope.rvalue_rl_count += 1;8758 const astgen = gz.astgen;
4703 _ = try gz.addBin(.store_to_block_ptr, block_scope.rl_ptr, result);8759 const gpa = astgen.gpa;
4704 return result;8760
8761 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8762 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
8763 try astgen.extra.ensureUnusedCapacity(
8764 gpa,
8765 @typeInfo(Zir.Inst.AllocExtended).Struct.fields.len +
8766 @as(usize, @boolToInt(args.type_inst != .none)) +
8767 @as(usize, @boolToInt(args.align_inst != .none)),
8768 );
8769 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.AllocExtended{
8770 .src_node = gz.nodeIndexToRelative(args.node),
8771 });
8772 if (args.type_inst != .none) {
8773 astgen.extra.appendAssumeCapacity(@enumToInt(args.type_inst));
8774 }
8775 if (args.align_inst != .none) {
8776 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
8777 }
8778
8779 const has_type: u4 = @boolToInt(args.type_inst != .none);
8780 const has_align: u4 = @boolToInt(args.align_inst != .none);
8781 const is_const: u4 = @boolToInt(args.is_const);
8782 const is_comptime: u4 = @boolToInt(args.is_comptime);
8783 const small: u16 = has_type | (has_align << 1) | (is_const << 2) | (is_comptime << 3);
8784
8785 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8786 astgen.instructions.appendAssumeCapacity(.{
8787 .tag = .extended,
8788 .data = .{ .extended = .{
8789 .opcode = .alloc,
8790 .small = small,
8791 .operand = payload_index,
8792 } },
8793 });
8794 gz.instructions.appendAssumeCapacity(new_index);
8795 return gz.indexToRef(new_index);
8796 }
8797
8798 fn addAsm(
8799 gz: *GenZir,
8800 args: struct {
8801 /// Absolute node index. This function does the conversion to offset from Decl.
8802 node: ast.Node.Index,
8803 asm_source: Zir.Inst.Ref,
8804 output_type_bits: u32,
8805 is_volatile: bool,
8806 outputs: []const Zir.Inst.Asm.Output,
8807 inputs: []const Zir.Inst.Asm.Input,
8808 clobbers: []const u32,
4705 },8809 },
8810 ) !Zir.Inst.Ref {
8811 const astgen = gz.astgen;
8812 const gpa = astgen.gpa;
8813
8814 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8815 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
8816 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Asm).Struct.fields.len +
8817 args.outputs.len * @typeInfo(Zir.Inst.Asm.Output).Struct.fields.len +
8818 args.inputs.len * @typeInfo(Zir.Inst.Asm.Input).Struct.fields.len +
8819 args.clobbers.len);
8820
8821 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Asm{
8822 .src_node = gz.nodeIndexToRelative(args.node),
8823 .asm_source = args.asm_source,
8824 .output_type_bits = args.output_type_bits,
8825 });
8826 for (args.outputs) |output| {
8827 _ = gz.astgen.addExtraAssumeCapacity(output);
8828 }
8829 for (args.inputs) |input| {
8830 _ = gz.astgen.addExtraAssumeCapacity(input);
8831 }
8832 gz.astgen.extra.appendSliceAssumeCapacity(args.clobbers);
8833
8834 // * 0b00000000_000XXXXX - `outputs_len`.
8835 // * 0b000000XX_XXX00000 - `inputs_len`.
8836 // * 0b0XXXXX00_00000000 - `clobbers_len`.
8837 // * 0bX0000000_00000000 - is volatile
8838 const small: u16 = @intCast(u16, args.outputs.len) |
8839 @intCast(u16, args.inputs.len << 5) |
8840 @intCast(u16, args.clobbers.len << 10) |
8841 (@as(u16, @boolToInt(args.is_volatile)) << 15);
8842
8843 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8844 astgen.instructions.appendAssumeCapacity(.{
8845 .tag = .extended,
8846 .data = .{ .extended = .{
8847 .opcode = .@"asm",
8848 .small = small,
8849 .operand = payload_index,
8850 } },
8851 });
8852 gz.instructions.appendAssumeCapacity(new_index);
8853 return gz.indexToRef(new_index);
8854 }
8855
8856 /// Note that this returns a `Zir.Inst.Index` not a ref.
8857 /// Does *not* append the block instruction to the scope.
8858 /// Leaves the `payload_index` field undefined.
8859 fn addBlock(gz: *GenZir, tag: Zir.Inst.Tag, node: ast.Node.Index) !Zir.Inst.Index {
8860 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8861 const gpa = gz.astgen.gpa;
8862 try gz.astgen.instructions.append(gpa, .{
8863 .tag = tag,
8864 .data = .{ .pl_node = .{
8865 .src_node = gz.nodeIndexToRelative(node),
8866 .payload_index = undefined,
8867 } },
8868 });
8869 return new_index;
8870 }
8871
8872 /// Note that this returns a `Zir.Inst.Index` not a ref.
8873 /// Leaves the `payload_index` field undefined.
8874 fn addCondBr(gz: *GenZir, tag: Zir.Inst.Tag, node: ast.Node.Index) !Zir.Inst.Index {
8875 const gpa = gz.astgen.gpa;
8876 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8877 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8878 try gz.astgen.instructions.append(gpa, .{
8879 .tag = tag,
8880 .data = .{ .pl_node = .{
8881 .src_node = gz.nodeIndexToRelative(node),
8882 .payload_index = undefined,
8883 } },
8884 });
8885 gz.instructions.appendAssumeCapacity(new_index);
8886 return new_index;
8887 }
8888
8889 fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
8890 src_node: ast.Node.Index,
8891 body_len: u32,
8892 fields_len: u32,
8893 decls_len: u32,
8894 layout: std.builtin.TypeInfo.ContainerLayout,
8895 }) !void {
8896 const astgen = gz.astgen;
8897 const gpa = astgen.gpa;
8898
8899 try astgen.extra.ensureUnusedCapacity(gpa, 4);
8900 const payload_index = @intCast(u32, astgen.extra.items.len);
8901
8902 if (args.src_node != 0) {
8903 const node_offset = gz.nodeIndexToRelative(args.src_node);
8904 astgen.extra.appendAssumeCapacity(@bitCast(u32, node_offset));
8905 }
8906 if (args.body_len != 0) {
8907 astgen.extra.appendAssumeCapacity(args.body_len);
8908 }
8909 if (args.fields_len != 0) {
8910 astgen.extra.appendAssumeCapacity(args.fields_len);
8911 }
8912 if (args.decls_len != 0) {
8913 astgen.extra.appendAssumeCapacity(args.decls_len);
8914 }
8915 astgen.instructions.set(inst, .{
8916 .tag = .extended,
8917 .data = .{ .extended = .{
8918 .opcode = .struct_decl,
8919 .small = @bitCast(u16, Zir.Inst.StructDecl.Small{
8920 .has_src_node = args.src_node != 0,
8921 .has_body_len = args.body_len != 0,
8922 .has_fields_len = args.fields_len != 0,
8923 .has_decls_len = args.decls_len != 0,
8924 .name_strategy = gz.anon_name_strategy,
8925 .layout = args.layout,
8926 }),
8927 .operand = payload_index,
8928 } },
8929 });
8930 }
8931
8932 fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
8933 src_node: ast.Node.Index,
8934 tag_type: Zir.Inst.Ref,
8935 body_len: u32,
8936 fields_len: u32,
8937 decls_len: u32,
8938 layout: std.builtin.TypeInfo.ContainerLayout,
8939 auto_enum_tag: bool,
8940 }) !void {
8941 const astgen = gz.astgen;
8942 const gpa = astgen.gpa;
8943
8944 try astgen.extra.ensureUnusedCapacity(gpa, 5);
8945 const payload_index = @intCast(u32, astgen.extra.items.len);
8946
8947 if (args.src_node != 0) {
8948 const node_offset = gz.nodeIndexToRelative(args.src_node);
8949 astgen.extra.appendAssumeCapacity(@bitCast(u32, node_offset));
8950 }
8951 if (args.tag_type != .none) {
8952 astgen.extra.appendAssumeCapacity(@enumToInt(args.tag_type));
8953 }
8954 if (args.body_len != 0) {
8955 astgen.extra.appendAssumeCapacity(args.body_len);
8956 }
8957 if (args.fields_len != 0) {
8958 astgen.extra.appendAssumeCapacity(args.fields_len);
8959 }
8960 if (args.decls_len != 0) {
8961 astgen.extra.appendAssumeCapacity(args.decls_len);
8962 }
8963 astgen.instructions.set(inst, .{
8964 .tag = .extended,
8965 .data = .{ .extended = .{
8966 .opcode = .union_decl,
8967 .small = @bitCast(u16, Zir.Inst.UnionDecl.Small{
8968 .has_src_node = args.src_node != 0,
8969 .has_tag_type = args.tag_type != .none,
8970 .has_body_len = args.body_len != 0,
8971 .has_fields_len = args.fields_len != 0,
8972 .has_decls_len = args.decls_len != 0,
8973 .name_strategy = gz.anon_name_strategy,
8974 .layout = args.layout,
8975 .auto_enum_tag = args.auto_enum_tag,
8976 }),
8977 .operand = payload_index,
8978 } },
8979 });
8980 }
8981
8982 fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
8983 src_node: ast.Node.Index,
8984 tag_type: Zir.Inst.Ref,
8985 body_len: u32,
8986 fields_len: u32,
8987 decls_len: u32,
8988 nonexhaustive: bool,
8989 }) !void {
8990 const astgen = gz.astgen;
8991 const gpa = astgen.gpa;
8992
8993 try astgen.extra.ensureUnusedCapacity(gpa, 5);
8994 const payload_index = @intCast(u32, astgen.extra.items.len);
8995
8996 if (args.src_node != 0) {
8997 const node_offset = gz.nodeIndexToRelative(args.src_node);
8998 astgen.extra.appendAssumeCapacity(@bitCast(u32, node_offset));
8999 }
9000 if (args.tag_type != .none) {
9001 astgen.extra.appendAssumeCapacity(@enumToInt(args.tag_type));
9002 }
9003 if (args.body_len != 0) {
9004 astgen.extra.appendAssumeCapacity(args.body_len);
9005 }
9006 if (args.fields_len != 0) {
9007 astgen.extra.appendAssumeCapacity(args.fields_len);
9008 }
9009 if (args.decls_len != 0) {
9010 astgen.extra.appendAssumeCapacity(args.decls_len);
9011 }
9012 astgen.instructions.set(inst, .{
9013 .tag = .extended,
9014 .data = .{ .extended = .{
9015 .opcode = .enum_decl,
9016 .small = @bitCast(u16, Zir.Inst.EnumDecl.Small{
9017 .has_src_node = args.src_node != 0,
9018 .has_tag_type = args.tag_type != .none,
9019 .has_body_len = args.body_len != 0,
9020 .has_fields_len = args.fields_len != 0,
9021 .has_decls_len = args.decls_len != 0,
9022 .name_strategy = gz.anon_name_strategy,
9023 .nonexhaustive = args.nonexhaustive,
9024 }),
9025 .operand = payload_index,
9026 } },
9027 });
9028 }
9029
9030 fn add(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Ref {
9031 return gz.indexToRef(try gz.addAsIndex(inst));
9032 }
9033
9034 fn addAsIndex(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Index {
9035 const gpa = gz.astgen.gpa;
9036 try gz.instructions.ensureUnusedCapacity(gpa, 1);
9037 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
9038
9039 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
9040 gz.astgen.instructions.appendAssumeCapacity(inst);
9041 gz.instructions.appendAssumeCapacity(new_index);
9042 return new_index;
9043 }
9044
9045 fn reserveInstructionIndex(gz: *GenZir) !Zir.Inst.Index {
9046 const gpa = gz.astgen.gpa;
9047 try gz.instructions.ensureUnusedCapacity(gpa, 1);
9048 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
9049
9050 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
9051 gz.astgen.instructions.len += 1;
9052 gz.instructions.appendAssumeCapacity(new_index);
9053 return new_index;
9054 }
9055};
9056
9057/// This can only be for short-lived references; the memory becomes invalidated
9058/// when another string is added.
9059fn nullTerminatedString(astgen: AstGen, index: usize) [*:0]const u8 {
9060 return @ptrCast([*:0]const u8, astgen.string_bytes.items.ptr) + index;
9061}
9062
9063fn declareNewName(
9064 astgen: *AstGen,
9065 start_scope: *Scope,
9066 name_index: u32,
9067 node: ast.Node.Index,
9068) !void {
9069 const gpa = astgen.gpa;
9070 var scope = start_scope;
9071 while (true) {
9072 switch (scope.tag) {
9073 .gen_zir => scope = scope.cast(GenZir).?.parent,
9074 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
9075 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
9076 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
9077 .namespace => {
9078 const ns = scope.cast(Scope.Namespace).?;
9079 const gop = try ns.decls.getOrPut(gpa, name_index);
9080 if (gop.found_existing) {
9081 const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(name_index)));
9082 defer gpa.free(name);
9083 return astgen.failNodeNotes(node, "redeclaration of '{s}'", .{
9084 name,
9085 }, &[_]u32{
9086 try astgen.errNoteNode(gop.entry.value, "other declaration here", .{}),
9087 });
9088 }
9089 gop.entry.value = node;
9090 break;
9091 },
9092 .top => break,
9093 }
4706 }9094 }
4707}9095}
src/BuiltinFn.zig+20-4
...@@ -39,6 +39,7 @@ pub const Tag = enum {...@@ -39,6 +39,7 @@ pub const Tag = enum {
39 error_to_int,39 error_to_int,
40 err_set_cast,40 err_set_cast,
41 @"export",41 @"export",
42 @"extern",
42 fence,43 fence,
43 field,44 field,
44 field_parent_ptr,45 field_parent_ptr,
...@@ -103,6 +104,7 @@ pub const Tag = enum {...@@ -103,6 +104,7 @@ pub const Tag = enum {
103 type_name,104 type_name,
104 TypeOf,105 TypeOf,
105 union_init,106 union_init,
107 Vector,
106};108};
107109
108tag: Tag,110tag: Tag,
...@@ -129,7 +131,7 @@ pub const list = list: {...@@ -129,7 +131,7 @@ pub const list = list: {
129 "@alignCast",131 "@alignCast",
130 .{132 .{
131 .tag = .align_cast,133 .tag = .align_cast,
132 .param_count = 1,134 .param_count = 2,
133 },135 },
134 },136 },
135 .{137 .{
...@@ -387,6 +389,13 @@ pub const list = list: {...@@ -387,6 +389,13 @@ pub const list = list: {
387 .param_count = 2,389 .param_count = 2,
388 },390 },
389 },391 },
392 .{
393 "@extern",
394 .{
395 .tag = .@"extern",
396 .param_count = 2,
397 },
398 },
390 .{399 .{
391 "@fence",400 "@fence",
392 .{401 .{
...@@ -414,14 +423,14 @@ pub const list = list: {...@@ -414,14 +423,14 @@ pub const list = list: {
414 "@floatCast",423 "@floatCast",
415 .{424 .{
416 .tag = .float_cast,425 .tag = .float_cast,
417 .param_count = 1,426 .param_count = 2,
418 },427 },
419 },428 },
420 .{429 .{
421 "@floatToInt",430 "@floatToInt",
422 .{431 .{
423 .tag = .float_to_int,432 .tag = .float_to_int,
424 .param_count = 1,433 .param_count = 2,
425 },434 },
426 },435 },
427 .{436 .{
...@@ -498,7 +507,7 @@ pub const list = list: {...@@ -498,7 +507,7 @@ pub const list = list: {
498 "@intToFloat",507 "@intToFloat",
499 .{508 .{
500 .tag = .int_to_float,509 .tag = .int_to_float,
501 .param_count = 1,510 .param_count = 2,
502 },511 },
503 },512 },
504 .{513 .{
...@@ -840,5 +849,12 @@ pub const list = list: {...@@ -840,5 +849,12 @@ pub const list = list: {
840 .param_count = 3,849 .param_count = 3,
841 },850 },
842 },851 },
852 .{
853 "@Vector",
854 .{
855 .tag = .Vector,
856 .param_count = 2,
857 },
858 },
843 });859 });
844};860};
src/Compilation.zig+398-143
...@@ -30,6 +30,7 @@ const c_codegen = @import("codegen/c.zig");...@@ -30,6 +30,7 @@ const c_codegen = @import("codegen/c.zig");
30const ThreadPool = @import("ThreadPool.zig");30const ThreadPool = @import("ThreadPool.zig");
31const WaitGroup = @import("WaitGroup.zig");31const WaitGroup = @import("WaitGroup.zig");
32const libtsan = @import("libtsan.zig");32const libtsan = @import("libtsan.zig");
33const Zir = @import("Zir.zig");
3334
34/// General-purpose allocator. Used for both temporary and long-term storage.35/// General-purpose allocator. Used for both temporary and long-term storage.
35gpa: *Allocator,36gpa: *Allocator,
...@@ -49,6 +50,11 @@ work_queue: std.fifo.LinearFifo(Job, .Dynamic),...@@ -49,6 +50,11 @@ work_queue: std.fifo.LinearFifo(Job, .Dynamic),
49/// gets linked with the Compilation.50/// gets linked with the Compilation.
50c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic),51c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic),
5152
53/// These jobs are to tokenize, parse, and astgen files, which may be outdated
54/// since the last compilation, as well as scan for `@import` and queue up
55/// additional jobs corresponding to those new files.
56astgen_work_queue: std.fifo.LinearFifo(*Module.Scope.File, .Dynamic),
57
52/// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator.58/// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator.
53/// This data is accessed by multiple threads and is protected by `mutex`.59/// This data is accessed by multiple threads and is protected by `mutex`.
54failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.ErrorMsg) = .{},60failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.ErrorMsg) = .{},
...@@ -141,6 +147,7 @@ emit_analysis: ?EmitLoc,...@@ -141,6 +147,7 @@ emit_analysis: ?EmitLoc,
141emit_docs: ?EmitLoc,147emit_docs: ?EmitLoc,
142148
143work_queue_wait_group: WaitGroup,149work_queue_wait_group: WaitGroup,
150astgen_wait_group: WaitGroup,
144151
145pub const InnerError = Module.InnerError;152pub const InnerError = Module.InnerError;
146153
...@@ -173,6 +180,8 @@ const Job = union(enum) {...@@ -173,6 +180,8 @@ const Job = union(enum) {
173 /// The source file containing the Decl has been updated, and so the180 /// The source file containing the Decl has been updated, and so the
174 /// Decl may need its line number information updated in the debug info.181 /// Decl may need its line number information updated in the debug info.
175 update_line_number: *Module.Decl,182 update_line_number: *Module.Decl,
183 /// The main source file for the package needs to be analyzed.
184 analyze_pkg: *Package,
176185
177 /// one of the glibc static objects186 /// one of the glibc static objects
178 glibc_crt_file: glibc.CRTFile,187 glibc_crt_file: glibc.CRTFile,
...@@ -194,8 +203,6 @@ const Job = union(enum) {...@@ -194,8 +203,6 @@ const Job = union(enum) {
194 /// calls to, for example, memcpy and memset.203 /// calls to, for example, memcpy and memset.
195 zig_libc: void,204 zig_libc: void,
196205
197 /// Generate builtin.zig source code and write it into the correct place.
198 generate_builtin_zig: void,
199 /// Use stage1 C++ code to compile zig code into an object file.206 /// Use stage1 C++ code to compile zig code into an object file.
200 stage1_module: void,207 stage1_module: void,
201208
...@@ -272,6 +279,7 @@ pub const MiscTask = enum {...@@ -272,6 +279,7 @@ pub const MiscTask = enum {
272 compiler_rt,279 compiler_rt,
273 libssp,280 libssp,
274 zig_libc,281 zig_libc,
282 analyze_pkg,
275};283};
276284
277pub const MiscError = struct {285pub const MiscError = struct {
...@@ -341,6 +349,7 @@ pub const AllErrors = struct {...@@ -341,6 +349,7 @@ pub const AllErrors = struct {
341 ttyconf.setColor(stderr, color);349 ttyconf.setColor(stderr, color);
342 try stderr.writeByteNTimes(' ', indent);350 try stderr.writeByteNTimes(' ', indent);
343 try stderr.writeAll(kind);351 try stderr.writeAll(kind);
352 ttyconf.setColor(stderr, .Reset);
344 ttyconf.setColor(stderr, .Bold);353 ttyconf.setColor(stderr, .Bold);
345 try stderr.print(" {s}\n", .{src.msg});354 try stderr.print(" {s}\n", .{src.msg});
346 ttyconf.setColor(stderr, .Reset);355 ttyconf.setColor(stderr, .Reset);
...@@ -384,10 +393,10 @@ pub const AllErrors = struct {...@@ -384,10 +393,10 @@ pub const AllErrors = struct {
384 const notes = try arena.allocator.alloc(Message, module_err_msg.notes.len);393 const notes = try arena.allocator.alloc(Message, module_err_msg.notes.len);
385 for (notes) |*note, i| {394 for (notes) |*note, i| {
386 const module_note = module_err_msg.notes[i];395 const module_note = module_err_msg.notes[i];
387 const source = try module_note.src_loc.fileScope().getSource(module);396 const source = try module_note.src_loc.file_scope.getSource(module.gpa);
388 const byte_offset = try module_note.src_loc.byteOffset();397 const byte_offset = try module_note.src_loc.byteOffset(module.gpa);
389 const loc = std.zig.findLineColumn(source, byte_offset);398 const loc = std.zig.findLineColumn(source, byte_offset);
390 const sub_file_path = module_note.src_loc.fileScope().sub_file_path;399 const sub_file_path = module_note.src_loc.file_scope.sub_file_path;
391 note.* = .{400 note.* = .{
392 .src = .{401 .src = .{
393 .src_path = try arena.allocator.dupe(u8, sub_file_path),402 .src_path = try arena.allocator.dupe(u8, sub_file_path),
...@@ -399,10 +408,18 @@ pub const AllErrors = struct {...@@ -399,10 +408,18 @@ pub const AllErrors = struct {
399 },408 },
400 };409 };
401 }410 }
402 const source = try module_err_msg.src_loc.fileScope().getSource(module);411 if (module_err_msg.src_loc.lazy == .entire_file) {
403 const byte_offset = try module_err_msg.src_loc.byteOffset();412 try errors.append(.{
413 .plain = .{
414 .msg = try arena.allocator.dupe(u8, module_err_msg.msg),
415 },
416 });
417 return;
418 }
419 const source = try module_err_msg.src_loc.file_scope.getSource(module.gpa);
420 const byte_offset = try module_err_msg.src_loc.byteOffset(module.gpa);
404 const loc = std.zig.findLineColumn(source, byte_offset);421 const loc = std.zig.findLineColumn(source, byte_offset);
405 const sub_file_path = module_err_msg.src_loc.fileScope().sub_file_path;422 const sub_file_path = module_err_msg.src_loc.file_scope.sub_file_path;
406 try errors.append(.{423 try errors.append(.{
407 .src = .{424 .src = .{
408 .src_path = try arena.allocator.dupe(u8, sub_file_path),425 .src_path = try arena.allocator.dupe(u8, sub_file_path),
...@@ -416,6 +433,84 @@ pub const AllErrors = struct {...@@ -416,6 +433,84 @@ pub const AllErrors = struct {
416 });433 });
417 }434 }
418435
436 pub fn addZir(
437 arena: *Allocator,
438 errors: *std.ArrayList(Message),
439 file: *Module.Scope.File,
440 ) !void {
441 assert(file.zir_loaded);
442 assert(file.tree_loaded);
443 assert(file.source_loaded);
444 const payload_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.compile_errors)];
445 assert(payload_index != 0);
446
447 const header = file.zir.extraData(Zir.Inst.CompileErrors, payload_index);
448 const items_len = header.data.items_len;
449 var extra_index = header.end;
450 var item_i: usize = 0;
451 while (item_i < items_len) : (item_i += 1) {
452 const item = file.zir.extraData(Zir.Inst.CompileErrors.Item, extra_index);
453 extra_index = item.end;
454
455 var notes: []Message = &[0]Message{};
456 if (item.data.notes != 0) {
457 const block = file.zir.extraData(Zir.Inst.Block, item.data.notes);
458 const body = file.zir.extra[block.end..][0..block.data.body_len];
459 notes = try arena.alloc(Message, body.len);
460 for (notes) |*note, i| {
461 const note_item = file.zir.extraData(Zir.Inst.CompileErrors.Item, body[i]);
462 const msg = file.zir.nullTerminatedString(note_item.data.msg);
463 const byte_offset = blk: {
464 const token_starts = file.tree.tokens.items(.start);
465 if (note_item.data.node != 0) {
466 const main_tokens = file.tree.nodes.items(.main_token);
467 const main_token = main_tokens[note_item.data.node];
468 break :blk token_starts[main_token];
469 }
470 break :blk token_starts[note_item.data.token] + note_item.data.byte_offset;
471 };
472 const loc = std.zig.findLineColumn(file.source, byte_offset);
473
474 note.* = .{
475 .src = .{
476 .src_path = try arena.dupe(u8, file.sub_file_path),
477 .msg = try arena.dupe(u8, msg),
478 .byte_offset = byte_offset,
479 .line = @intCast(u32, loc.line),
480 .column = @intCast(u32, loc.column),
481 .notes = &.{}, // TODO rework this function to be recursive
482 .source_line = try arena.dupe(u8, loc.source_line),
483 },
484 };
485 }
486 }
487
488 const msg = file.zir.nullTerminatedString(item.data.msg);
489 const byte_offset = blk: {
490 const token_starts = file.tree.tokens.items(.start);
491 if (item.data.node != 0) {
492 const main_tokens = file.tree.nodes.items(.main_token);
493 const main_token = main_tokens[item.data.node];
494 break :blk token_starts[main_token];
495 }
496 break :blk token_starts[item.data.token] + item.data.byte_offset;
497 };
498 const loc = std.zig.findLineColumn(file.source, byte_offset);
499
500 try errors.append(.{
501 .src = .{
502 .src_path = try arena.dupe(u8, file.sub_file_path),
503 .msg = try arena.dupe(u8, msg),
504 .byte_offset = byte_offset,
505 .line = @intCast(u32, loc.line),
506 .column = @intCast(u32, loc.column),
507 .notes = notes,
508 .source_line = try arena.dupe(u8, loc.source_line),
509 },
510 });
511 }
512 }
513
419 fn addPlain(514 fn addPlain(
420 arena: *std.heap.ArenaAllocator,515 arena: *std.heap.ArenaAllocator,
421 errors: *std.ArrayList(Message),516 errors: *std.ArrayList(Message),
...@@ -530,7 +625,7 @@ pub const InitOptions = struct {...@@ -530,7 +625,7 @@ pub const InitOptions = struct {
530 /// is externally modified - essentially anything other than zig-cache - then625 /// is externally modified - essentially anything other than zig-cache - then
531 /// this flag would be set to disable this machinery to avoid false positives.626 /// this flag would be set to disable this machinery to avoid false positives.
532 disable_lld_caching: bool = false,627 disable_lld_caching: bool = false,
533 object_format: ?std.builtin.ObjectFormat = null,628 object_format: ?std.Target.ObjectFormat = null,
534 optimize_mode: std.builtin.Mode = .Debug,629 optimize_mode: std.builtin.Mode = .Debug,
535 keep_source_files_loaded: bool = false,630 keep_source_files_loaded: bool = false,
536 clang_argv: []const []const u8 = &[0][]const u8{},631 clang_argv: []const []const u8 = &[0][]const u8{},
...@@ -1044,45 +1139,56 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1044,45 +1139,56 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
10441139
1045 try std_pkg.add(gpa, "builtin", builtin_pkg);1140 try std_pkg.add(gpa, "builtin", builtin_pkg);
1046 try std_pkg.add(gpa, "root", root_pkg);1141 try std_pkg.add(gpa, "root", root_pkg);
1142 try std_pkg.add(gpa, "std", std_pkg);
1143
1144 try builtin_pkg.add(gpa, "std", std_pkg);
1145 try builtin_pkg.add(gpa, "builtin", builtin_pkg);
1047 }1146 }
10481147
1148 // Pre-open the directory handles for cached ZIR code so that it does not need
1149 // to redundantly happen for each AstGen operation.
1150 const zir_sub_dir = "z";
1151
1152 var local_zir_dir = try options.local_cache_directory.handle.makeOpenPath(zir_sub_dir, .{});
1153 errdefer local_zir_dir.close();
1154 const local_zir_cache: Directory = .{
1155 .handle = local_zir_dir,
1156 .path = try options.local_cache_directory.join(arena, &[_][]const u8{zir_sub_dir}),
1157 };
1158 var global_zir_dir = try options.global_cache_directory.handle.makeOpenPath(zir_sub_dir, .{});
1159 errdefer global_zir_dir.close();
1160 const global_zir_cache: Directory = .{
1161 .handle = global_zir_dir,
1162 .path = try options.global_cache_directory.join(arena, &[_][]const u8{zir_sub_dir}),
1163 };
1164
1165 const emit_h: ?*Module.GlobalEmitH = if (options.emit_h) |loc| eh: {
1166 const eh = try gpa.create(Module.GlobalEmitH);
1167 eh.* = .{ .loc = loc };
1168 break :eh eh;
1169 } else null;
1170 errdefer if (emit_h) |eh| gpa.destroy(eh);
1171
1049 // TODO when we implement serialization and deserialization of incremental1172 // TODO when we implement serialization and deserialization of incremental
1050 // compilation metadata, this is where we would load it. We have open a handle1173 // compilation metadata, this is where we would load it. We have open a handle
1051 // to the directory where the output either already is, or will be.1174 // to the directory where the output either already is, or will be.
1052 // However we currently do not have serialization of such metadata, so for now1175 // However we currently do not have serialization of such metadata, so for now
1053 // we set up an empty Module that does the entire compilation fresh.1176 // we set up an empty Module that does the entire compilation fresh.
10541177
1055 const root_scope = try gpa.create(Module.Scope.File);
1056 errdefer gpa.destroy(root_scope);
1057
1058 const struct_ty = try Type.Tag.empty_struct.create(gpa, &root_scope.root_container);
1059 root_scope.* = .{
1060 // TODO this is duped so it can be freed in Container.deinit
1061 .sub_file_path = try gpa.dupe(u8, root_pkg.root_src_path),
1062 .source = .{ .unloaded = {} },
1063 .tree = undefined,
1064 .status = .never_loaded,
1065 .pkg = root_pkg,
1066 .root_container = .{
1067 .file_scope = root_scope,
1068 .decls = .{},
1069 .ty = struct_ty,
1070 .parent_name_hash = root_pkg.namespace_hash,
1071 },
1072 };
1073
1074 const module = try arena.create(Module);1178 const module = try arena.create(Module);
1075 errdefer module.deinit();1179 errdefer module.deinit();
1076 module.* = .{1180 module.* = .{
1077 .gpa = gpa,1181 .gpa = gpa,
1078 .comp = comp,1182 .comp = comp,
1079 .root_pkg = root_pkg,1183 .root_pkg = root_pkg,
1080 .root_scope = root_scope,
1081 .zig_cache_artifact_directory = zig_cache_artifact_directory,1184 .zig_cache_artifact_directory = zig_cache_artifact_directory,
1082 .emit_h = options.emit_h,1185 .global_zir_cache = global_zir_cache,
1186 .local_zir_cache = local_zir_cache,
1187 .emit_h = emit_h,
1083 .error_name_list = try std.ArrayListUnmanaged([]const u8).initCapacity(gpa, 1),1188 .error_name_list = try std.ArrayListUnmanaged([]const u8).initCapacity(gpa, 1),
1084 };1189 };
1085 module.error_name_list.appendAssumeCapacity("(no error)");1190 module.error_name_list.appendAssumeCapacity("(no error)");
1191
1086 break :blk module;1192 break :blk module;
1087 } else blk: {1193 } else blk: {
1088 if (options.emit_h != null) return error.NoZigModuleForCHeader;1194 if (options.emit_h != null) return error.NoZigModuleForCHeader;
...@@ -1229,6 +1335,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1229,6 +1335,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1229 .emit_docs = options.emit_docs,1335 .emit_docs = options.emit_docs,
1230 .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),1336 .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),
1231 .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),1337 .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),
1338 .astgen_work_queue = std.fifo.LinearFifo(*Module.Scope.File, .Dynamic).init(gpa),
1232 .keep_source_files_loaded = options.keep_source_files_loaded,1339 .keep_source_files_loaded = options.keep_source_files_loaded,
1233 .use_clang = use_clang,1340 .use_clang = use_clang,
1234 .clang_argv = options.clang_argv,1341 .clang_argv = options.clang_argv,
...@@ -1257,6 +1364,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1257,6 +1364,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1257 .test_evented_io = options.test_evented_io,1364 .test_evented_io = options.test_evented_io,
1258 .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs,1365 .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs,
1259 .work_queue_wait_group = undefined,1366 .work_queue_wait_group = undefined,
1367 .astgen_wait_group = undefined,
1260 };1368 };
1261 break :comp comp;1369 break :comp comp;
1262 };1370 };
...@@ -1265,9 +1373,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1265,9 +1373,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1265 try comp.work_queue_wait_group.init();1373 try comp.work_queue_wait_group.init();
1266 errdefer comp.work_queue_wait_group.deinit();1374 errdefer comp.work_queue_wait_group.deinit();
12671375
1268 if (comp.bin_file.options.module) |mod| {1376 try comp.astgen_wait_group.init();
1269 try comp.work_queue.writeItem(.{ .generate_builtin_zig = {} });1377 errdefer comp.astgen_wait_group.deinit();
1270 }
12711378
1272 // Add a `CObject` for each `c_source_files`.1379 // Add a `CObject` for each `c_source_files`.
1273 try comp.c_object_table.ensureCapacity(gpa, options.c_source_files.len);1380 try comp.c_object_table.ensureCapacity(gpa, options.c_source_files.len);
...@@ -1400,6 +1507,7 @@ pub fn destroy(self: *Compilation) void {...@@ -1400,6 +1507,7 @@ pub fn destroy(self: *Compilation) void {
1400 const gpa = self.gpa;1507 const gpa = self.gpa;
1401 self.work_queue.deinit();1508 self.work_queue.deinit();
1402 self.c_object_work_queue.deinit();1509 self.c_object_work_queue.deinit();
1510 self.astgen_work_queue.deinit();
14031511
1404 {1512 {
1405 var it = self.crt_files.iterator();1513 var it = self.crt_files.iterator();
...@@ -1450,6 +1558,7 @@ pub fn destroy(self: *Compilation) void {...@@ -1450,6 +1558,7 @@ pub fn destroy(self: *Compilation) void {
1450 if (self.owned_link_dir) |*dir| dir.close();1558 if (self.owned_link_dir) |*dir| dir.close();
14511559
1452 self.work_queue_wait_group.deinit();1560 self.work_queue_wait_group.deinit();
1561 self.astgen_wait_group.deinit();
14531562
1454 // This destroys `self`.1563 // This destroys `self`.
1455 self.arena_state.promote(gpa).deinit();1564 self.arena_state.promote(gpa).deinit();
...@@ -1489,31 +1598,20 @@ pub fn update(self: *Compilation) !void {...@@ -1489,31 +1598,20 @@ pub fn update(self: *Compilation) !void {
1489 module.compile_log_text.shrinkAndFree(module.gpa, 0);1598 module.compile_log_text.shrinkAndFree(module.gpa, 0);
1490 module.generation += 1;1599 module.generation += 1;
14911600
1492 // TODO Detect which source files changed.1601 // Make sure std.zig is inside the import_table. We unconditionally need
1493 // Until then we simulate a full cache miss. Source files could have been loaded1602 // it for start.zig.
1494 // for any reason; to force a refresh we unload now.1603 const std_pkg = module.root_pkg.table.get("std").?;
1495 module.unloadFile(module.root_scope);1604 _ = try module.importPkg(module.root_pkg, std_pkg);
1496 module.failed_root_src_file = null;
1497 module.analyzeContainer(&module.root_scope.root_container) catch |err| switch (err) {
1498 error.AnalysisFail => {
1499 assert(self.totalErrorCount() != 0);
1500 },
1501 error.OutOfMemory => return error.OutOfMemory,
1502 else => |e| {
1503 module.failed_root_src_file = e;
1504 },
1505 };
15061605
1507 // TODO only analyze imports if they are still referenced1606 // Put a work item in for every known source file to detect if
1607 // it changed, and, if so, re-compute ZIR and then queue the job
1608 // to update it.
1609 try self.astgen_work_queue.ensureUnusedCapacity(module.import_table.count());
1508 for (module.import_table.items()) |entry| {1610 for (module.import_table.items()) |entry| {
1509 module.unloadFile(entry.value);1611 self.astgen_work_queue.writeItemAssumeCapacity(entry.value);
1510 module.analyzeContainer(&entry.value.root_container) catch |err| switch (err) {
1511 error.AnalysisFail => {
1512 assert(self.totalErrorCount() != 0);
1513 },
1514 else => |e| return e,
1515 };
1516 }1612 }
1613
1614 try self.work_queue.writeItem(.{ .analyze_pkg = std_pkg });
1517 }1615 }
1518 }1616 }
15191617
...@@ -1522,16 +1620,24 @@ pub fn update(self: *Compilation) !void {...@@ -1522,16 +1620,24 @@ pub fn update(self: *Compilation) !void {
1522 if (!use_stage1) {1620 if (!use_stage1) {
1523 if (self.bin_file.options.module) |module| {1621 if (self.bin_file.options.module) |module| {
1524 // Process the deletion set. We use a while loop here because the1622 // Process the deletion set. We use a while loop here because the
1525 // deletion set may grow as we call `deleteDecl` within this loop,1623 // deletion set may grow as we call `clearDecl` within this loop,
1526 // and more unreferenced Decls are revealed.1624 // and more unreferenced Decls are revealed.
1527 var entry_i: usize = 0;1625 while (module.deletion_set.entries.items.len != 0) {
1528 while (entry_i < module.deletion_set.entries.items.len) : (entry_i += 1) {1626 const decl = module.deletion_set.entries.items[0].key;
1529 const decl = module.deletion_set.entries.items[entry_i].key;
1530 assert(decl.deletion_flag);1627 assert(decl.deletion_flag);
1531 assert(decl.dependants.items().len == 0);1628 assert(decl.dependants.count() == 0);
1532 try module.deleteDecl(decl, null);1629 const is_anon = if (decl.zir_decl_index == 0) blk: {
1630 break :blk decl.namespace.anon_decls.swapRemove(decl) != null;
1631 } else false;
1632
1633 try module.clearDecl(decl, null);
1634
1635 if (is_anon) {
1636 decl.destroy(module);
1637 }
1533 }1638 }
1534 module.deletion_set.shrinkRetainingCapacity(0);1639
1640 try module.processExports();
1535 }1641 }
1536 }1642 }
15371643
...@@ -1553,9 +1659,16 @@ pub fn update(self: *Compilation) !void {...@@ -1553,9 +1659,16 @@ pub fn update(self: *Compilation) !void {
15531659
1554 // If there are any errors, we anticipate the source files being loaded1660 // If there are any errors, we anticipate the source files being loaded
1555 // to report error messages. Otherwise we unload all source files to save memory.1661 // to report error messages. Otherwise we unload all source files to save memory.
1662 // The ZIR needs to stay loaded in memory because (1) Decl objects contain references
1663 // to it, and (2) generic instantiations, comptime calls, inline calls will need
1664 // to reference the ZIR.
1556 if (self.totalErrorCount() == 0 and !self.keep_source_files_loaded) {1665 if (self.totalErrorCount() == 0 and !self.keep_source_files_loaded) {
1557 if (self.bin_file.options.module) |module| {1666 if (self.bin_file.options.module) |module| {
1558 module.root_scope.unload(self.gpa);1667 for (module.import_table.items()) |entry| {
1668 const file = entry.value;
1669 file.unloadTree(self.gpa);
1670 file.unloadSource(self.gpa);
1671 }
1559 }1672 }
1560 }1673 }
1561}1674}
...@@ -1576,24 +1689,36 @@ pub fn totalErrorCount(self: *Compilation) usize {...@@ -1576,24 +1689,36 @@ pub fn totalErrorCount(self: *Compilation) usize {
1576 var total: usize = self.failed_c_objects.count() + self.misc_failures.count();1689 var total: usize = self.failed_c_objects.count() + self.misc_failures.count();
15771690
1578 if (self.bin_file.options.module) |module| {1691 if (self.bin_file.options.module) |module| {
1579 total += module.failed_exports.items().len +1692 total += module.failed_exports.items().len;
1580 module.failed_files.items().len +1693
1581 @boolToInt(module.failed_root_src_file != null);1694 for (module.failed_files.items()) |entry| {
1695 if (entry.value) |_| {
1696 total += 1;
1697 } else {
1698 const file = entry.key;
1699 assert(file.zir_loaded);
1700 const payload_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.compile_errors)];
1701 assert(payload_index != 0);
1702 const header = file.zir.extraData(Zir.Inst.CompileErrors, payload_index);
1703 total += header.data.items_len;
1704 }
1705 }
1706
1582 // Skip errors for Decls within files that failed parsing.1707 // Skip errors for Decls within files that failed parsing.
1583 // When a parse error is introduced, we keep all the semantic analysis for1708 // When a parse error is introduced, we keep all the semantic analysis for
1584 // the previous parse success, including compile errors, but we cannot1709 // the previous parse success, including compile errors, but we cannot
1585 // emit them until the file succeeds parsing.1710 // emit them until the file succeeds parsing.
1586 for (module.failed_decls.items()) |entry| {1711 for (module.failed_decls.items()) |entry| {
1587 if (entry.key.container.file_scope.status == .unloaded_parse_failure) {1712 if (entry.key.namespace.file_scope.okToReportErrors()) {
1588 continue;1713 total += 1;
1589 }1714 }
1590 total += 1;
1591 }1715 }
1592 for (module.emit_h_failed_decls.items()) |entry| {1716 if (module.emit_h) |emit_h| {
1593 if (entry.key.container.file_scope.status == .unloaded_parse_failure) {1717 for (emit_h.failed_decls.items()) |entry| {
1594 continue;1718 if (entry.key.namespace.file_scope.okToReportErrors()) {
1719 total += 1;
1720 }
1595 }1721 }
1596 total += 1;
1597 }1722 }
1598 }1723 }
15991724
...@@ -1642,36 +1767,35 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {...@@ -1642,36 +1767,35 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
1642 }1767 }
1643 if (self.bin_file.options.module) |module| {1768 if (self.bin_file.options.module) |module| {
1644 for (module.failed_files.items()) |entry| {1769 for (module.failed_files.items()) |entry| {
1645 try AllErrors.add(module, &arena, &errors, entry.value.*);1770 if (entry.value) |msg| {
1771 try AllErrors.add(module, &arena, &errors, msg.*);
1772 } else {
1773 // Must be ZIR errors. In order for ZIR errors to exist, the parsing
1774 // must have completed successfully.
1775 const tree = try entry.key.getTree(module.gpa);
1776 assert(tree.errors.len == 0);
1777 try AllErrors.addZir(&arena.allocator, &errors, entry.key);
1778 }
1646 }1779 }
1647 for (module.failed_decls.items()) |entry| {1780 for (module.failed_decls.items()) |entry| {
1648 if (entry.key.container.file_scope.status == .unloaded_parse_failure) {1781 // Skip errors for Decls within files that had a parse failure.
1649 // Skip errors for Decls within files that had a parse failure.1782 // We'll try again once parsing succeeds.
1650 // We'll try again once parsing succeeds.1783 if (entry.key.namespace.file_scope.okToReportErrors()) {
1651 continue;1784 try AllErrors.add(module, &arena, &errors, entry.value.*);
1652 }1785 }
1653 try AllErrors.add(module, &arena, &errors, entry.value.*);
1654 }1786 }
1655 for (module.emit_h_failed_decls.items()) |entry| {1787 if (module.emit_h) |emit_h| {
1656 if (entry.key.container.file_scope.status == .unloaded_parse_failure) {1788 for (emit_h.failed_decls.items()) |entry| {
1657 // Skip errors for Decls within files that had a parse failure.1789 // Skip errors for Decls within files that had a parse failure.
1658 // We'll try again once parsing succeeds.1790 // We'll try again once parsing succeeds.
1659 continue;1791 if (entry.key.namespace.file_scope.okToReportErrors()) {
1792 try AllErrors.add(module, &arena, &errors, entry.value.*);
1793 }
1660 }1794 }
1661 try AllErrors.add(module, &arena, &errors, entry.value.*);
1662 }1795 }
1663 for (module.failed_exports.items()) |entry| {1796 for (module.failed_exports.items()) |entry| {
1664 try AllErrors.add(module, &arena, &errors, entry.value.*);1797 try AllErrors.add(module, &arena, &errors, entry.value.*);
1665 }1798 }
1666 if (module.failed_root_src_file) |err| {
1667 const file_path = try module.root_pkg.root_src_directory.join(&arena.allocator, &[_][]const u8{
1668 module.root_pkg.root_src_path,
1669 });
1670 const msg = try std.fmt.allocPrint(&arena.allocator, "unable to read {s}: {s}", .{
1671 file_path, @errorName(err),
1672 });
1673 try AllErrors.addPlain(&arena, &errors, msg);
1674 }
1675 }1799 }
16761800
1677 if (errors.items.len == 0 and self.link_error_flags.no_entry_point_found) {1801 if (errors.items.len == 0 and self.link_error_flags.no_entry_point_found) {
...@@ -1686,8 +1810,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {...@@ -1686,8 +1810,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
1686 const compile_log_items = module.compile_log_decls.items();1810 const compile_log_items = module.compile_log_decls.items();
1687 if (errors.items.len == 0 and compile_log_items.len != 0) {1811 if (errors.items.len == 0 and compile_log_items.len != 0) {
1688 // First one will be the error; subsequent ones will be notes.1812 // First one will be the error; subsequent ones will be notes.
1813 const src_loc = compile_log_items[0].key.nodeOffsetSrcLoc(compile_log_items[0].value);
1689 const err_msg = Module.ErrorMsg{1814 const err_msg = Module.ErrorMsg{
1690 .src_loc = compile_log_items[0].value,1815 .src_loc = src_loc,
1691 .msg = "found compile log statement",1816 .msg = "found compile log statement",
1692 .notes = try self.gpa.alloc(Module.ErrorMsg, compile_log_items.len - 1),1817 .notes = try self.gpa.alloc(Module.ErrorMsg, compile_log_items.len - 1),
1693 };1818 };
...@@ -1695,7 +1820,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {...@@ -1695,7 +1820,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
16951820
1696 for (compile_log_items[1..]) |entry, i| {1821 for (compile_log_items[1..]) |entry, i| {
1697 err_msg.notes[i] = .{1822 err_msg.notes[i] = .{
1698 .src_loc = entry.value,1823 .src_loc = entry.key.nodeOffsetSrcLoc(entry.value),
1699 .msg = "also here",1824 .msg = "also here",
1700 };1825 };
1701 }1826 }
...@@ -1725,17 +1850,51 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1725,17 +1850,51 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1725 defer main_progress_node.end();1850 defer main_progress_node.end();
1726 if (self.color == .off) progress.terminal = null;1851 if (self.color == .off) progress.terminal = null;
17271852
1728 var c_comp_progress_node = main_progress_node.start("Compile C Objects", self.c_source_files.len);1853 // If we need to write out builtin.zig, it needs to be done before starting
1729 defer c_comp_progress_node.end();1854 // the AstGen tasks.
1855 if (self.bin_file.options.module) |mod| {
1856 if (mod.job_queued_update_builtin_zig) {
1857 mod.job_queued_update_builtin_zig = false;
1858 try self.updateBuiltinZigFile(mod);
1859 }
1860 }
1861
1862 // Here we queue up all the AstGen tasks first, followed by C object compilation.
1863 // We wait until the AstGen tasks are all completed before proceeding to the
1864 // (at least for now) single-threaded main work queue. However, C object compilation
1865 // only needs to be finished by the end of this function.
1866
1867 var zir_prog_node = main_progress_node.start("AstGen", self.astgen_work_queue.count);
1868 defer zir_prog_node.end();
1869
1870 var c_obj_prog_node = main_progress_node.start("Compile C Objects", self.c_source_files.len);
1871 defer c_obj_prog_node.end();
17301872
1731 self.work_queue_wait_group.reset();1873 self.work_queue_wait_group.reset();
1732 defer self.work_queue_wait_group.wait();1874 defer self.work_queue_wait_group.wait();
17331875
1734 while (self.c_object_work_queue.readItem()) |c_object| {1876 {
1735 self.work_queue_wait_group.start();1877 self.astgen_wait_group.reset();
1736 try self.thread_pool.spawn(workerUpdateCObject, .{1878 defer self.astgen_wait_group.wait();
1737 self, c_object, &c_comp_progress_node, &self.work_queue_wait_group,1879
1738 });1880 while (self.astgen_work_queue.readItem()) |file| {
1881 self.astgen_wait_group.start();
1882 try self.thread_pool.spawn(workerAstGenFile, .{
1883 self, file, &zir_prog_node, &self.astgen_wait_group,
1884 });
1885 }
1886
1887 while (self.c_object_work_queue.readItem()) |c_object| {
1888 self.work_queue_wait_group.start();
1889 try self.thread_pool.spawn(workerUpdateCObject, .{
1890 self, c_object, &c_obj_prog_node, &self.work_queue_wait_group,
1891 });
1892 }
1893 }
1894
1895 // Iterate over all the files and look for outdated and deleted declarations.
1896 if (self.bin_file.options.module) |mod| {
1897 try mod.processOutdatedAndDeletedDecls();
1739 }1898 }
17401899
1741 while (self.work_queue.readItem()) |work_item| switch (work_item) {1900 while (self.work_queue.readItem()) |work_item| switch (work_item) {
...@@ -1744,6 +1903,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1744,6 +1903,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1744 .in_progress => unreachable,1903 .in_progress => unreachable,
1745 .outdated => unreachable,1904 .outdated => unreachable,
17461905
1906 .file_failure,
1747 .sema_failure,1907 .sema_failure,
1748 .codegen_failure,1908 .codegen_failure,
1749 .dependency_failure,1909 .dependency_failure,
...@@ -1754,7 +1914,8 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1754,7 +1914,8 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1754 if (build_options.omit_stage2)1914 if (build_options.omit_stage2)
1755 @panic("sadly stage2 is omitted from this build to save memory on the CI server");1915 @panic("sadly stage2 is omitted from this build to save memory on the CI server");
1756 const module = self.bin_file.options.module.?;1916 const module = self.bin_file.options.module.?;
1757 if (decl.typed_value.most_recent.typed_value.val.castTag(.function)) |payload| {1917 assert(decl.has_tv);
1918 if (decl.val.castTag(.function)) |payload| {
1758 const func = payload.data;1919 const func = payload.data;
1759 switch (func.state) {1920 switch (func.state) {
1760 .queued => module.analyzeFnBody(decl, func) catch |err| switch (err) {1921 .queued => module.analyzeFnBody(decl, func) catch |err| switch (err) {
...@@ -1771,8 +1932,8 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1771,8 +1932,8 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1771 }1932 }
1772 // Here we tack on additional allocations to the Decl's arena. The allocations1933 // Here we tack on additional allocations to the Decl's arena. The allocations
1773 // are lifetime annotations in the ZIR.1934 // are lifetime annotations in the ZIR.
1774 var decl_arena = decl.typed_value.most_recent.arena.?.promote(module.gpa);1935 var decl_arena = decl.value_arena.?.promote(module.gpa);
1775 defer decl.typed_value.most_recent.arena.?.* = decl_arena.state;1936 defer decl.value_arena.?.* = decl_arena.state;
1776 log.debug("analyze liveness of {s}", .{decl.name});1937 log.debug("analyze liveness of {s}", .{decl.name});
1777 try liveness.analyze(module.gpa, &decl_arena.allocator, func.body);1938 try liveness.analyze(module.gpa, &decl_arena.allocator, func.body);
17781939
...@@ -1781,10 +1942,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1781,10 +1942,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1781 }1942 }
1782 }1943 }
17831944
1784 log.debug("calling updateDecl on '{s}', type={}", .{1945 assert(decl.ty.hasCodeGenBits());
1785 decl.name, decl.typed_value.most_recent.typed_value.ty,
1786 });
1787 assert(decl.typed_value.most_recent.typed_value.ty.hasCodeGenBits());
17881946
1789 self.bin_file.updateDecl(module, decl) catch |err| switch (err) {1947 self.bin_file.updateDecl(module, decl) catch |err| switch (err) {
1790 error.OutOfMemory => return error.OutOfMemory,1948 error.OutOfMemory => return error.OutOfMemory,
...@@ -1811,6 +1969,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1811,6 +1969,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1811 .in_progress => unreachable,1969 .in_progress => unreachable,
1812 .outdated => unreachable,1970 .outdated => unreachable,
18131971
1972 .file_failure,
1814 .sema_failure,1973 .sema_failure,
1815 .dependency_failure,1974 .dependency_failure,
1816 .sema_failure_retryable,1975 .sema_failure_retryable,
...@@ -1822,10 +1981,10 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1822,10 +1981,10 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1822 if (build_options.omit_stage2)1981 if (build_options.omit_stage2)
1823 @panic("sadly stage2 is omitted from this build to save memory on the CI server");1982 @panic("sadly stage2 is omitted from this build to save memory on the CI server");
1824 const module = self.bin_file.options.module.?;1983 const module = self.bin_file.options.module.?;
1825 const emit_loc = module.emit_h.?;1984 const emit_h = module.emit_h.?;
1826 const tv = decl.typed_value.most_recent.typed_value;1985 _ = try emit_h.decl_table.getOrPut(module.gpa, decl);
1827 const emit_h = decl.getEmitH(module);1986 const decl_emit_h = decl.getEmitH(module);
1828 const fwd_decl = &emit_h.fwd_decl;1987 const fwd_decl = &decl_emit_h.fwd_decl;
1829 fwd_decl.shrinkRetainingCapacity(0);1988 fwd_decl.shrinkRetainingCapacity(0);
18301989
1831 var dg: c_codegen.DeclGen = .{1990 var dg: c_codegen.DeclGen = .{
...@@ -1840,7 +1999,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1840,7 +1999,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
18401999
1841 c_codegen.genHeader(&dg) catch |err| switch (err) {2000 c_codegen.genHeader(&dg) catch |err| switch (err) {
1842 error.AnalysisFail => {2001 error.AnalysisFail => {
1843 try module.emit_h_failed_decls.put(module.gpa, decl, dg.error_msg.?);2002 try emit_h.failed_decls.put(module.gpa, decl, dg.error_msg.?);
1844 continue;2003 continue;
1845 },2004 },
1846 else => |e| return e,2005 else => |e| return e,
...@@ -1874,6 +2033,22 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1874,6 +2033,22 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1874 decl.analysis = .codegen_failure_retryable;2033 decl.analysis = .codegen_failure_retryable;
1875 };2034 };
1876 },2035 },
2036 .analyze_pkg => |pkg| {
2037 if (build_options.omit_stage2)
2038 @panic("sadly stage2 is omitted from this build to save memory on the CI server");
2039 const module = self.bin_file.options.module.?;
2040 module.semaPkg(pkg) catch |err| switch (err) {
2041 error.CurrentWorkingDirectoryUnlinked,
2042 error.Unexpected,
2043 => try self.setMiscFailure(
2044 .analyze_pkg,
2045 "unexpected problem analyzing package '{s}'",
2046 .{pkg.root_src_path},
2047 ),
2048 error.OutOfMemory => return error.OutOfMemory,
2049 error.AnalysisFail => continue,
2050 };
2051 },
1877 .glibc_crt_file => |crt_file| {2052 .glibc_crt_file => |crt_file| {
1878 glibc.buildCRTFile(self, crt_file) catch |err| {2053 glibc.buildCRTFile(self, crt_file) catch |err| {
1879 // TODO Surface more error details.2054 // TODO Surface more error details.
...@@ -2027,10 +2202,6 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -2027,10 +2202,6 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
2027 ),2202 ),
2028 };2203 };
2029 },2204 },
2030 .generate_builtin_zig => {
2031 // This Job is only queued up if there is a zig module.
2032 try self.updateBuiltinZigFile(self.bin_file.options.module.?);
2033 },
2034 .stage1_module => {2205 .stage1_module => {
2035 if (!build_options.is_stage1)2206 if (!build_options.is_stage1)
2036 unreachable;2207 unreachable;
...@@ -2042,6 +2213,58 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -2042,6 +2213,58 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
2042 };2213 };
2043}2214}
20442215
2216fn workerAstGenFile(
2217 comp: *Compilation,
2218 file: *Module.Scope.File,
2219 prog_node: *std.Progress.Node,
2220 wg: *WaitGroup,
2221) void {
2222 defer wg.finish();
2223
2224 const mod = comp.bin_file.options.module.?;
2225 mod.astGenFile(file, prog_node) catch |err| switch (err) {
2226 error.AnalysisFail => return,
2227 else => {
2228 file.status = .retryable_failure;
2229 comp.reportRetryableAstGenError(file, err) catch |oom| switch (oom) {
2230 // Swallowing this error is OK because it's implied to be OOM when
2231 // there is a missing `failed_files` error message.
2232 error.OutOfMemory => {},
2233 };
2234 return;
2235 },
2236 };
2237
2238 // Pre-emptively look for `@import` paths and queue them up.
2239 // If we experience an error preemptively fetching the
2240 // file, just ignore it and let it happen again later during Sema.
2241 assert(file.zir_loaded);
2242 const imports_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.imports)];
2243 if (imports_index != 0) {
2244 const imports_len = file.zir.extra[imports_index];
2245
2246 for (file.zir.extra[imports_index + 1 ..][0..imports_len]) |str_index| {
2247 const import_path = file.zir.nullTerminatedString(str_index);
2248
2249 const import_result = blk: {
2250 const lock = comp.mutex.acquire();
2251 defer lock.release();
2252
2253 break :blk mod.importFile(file, import_path) catch continue;
2254 };
2255 if (import_result.is_new) {
2256 wg.start();
2257 comp.thread_pool.spawn(workerAstGenFile, .{
2258 comp, import_result.file, prog_node, wg,
2259 }) catch {
2260 wg.finish();
2261 continue;
2262 };
2263 }
2264 }
2265 }
2266}
2267
2045pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest {2268pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest {
2046 var man = comp.cache_parent.obtain();2269 var man = comp.cache_parent.obtain();
20472270
...@@ -2241,7 +2464,33 @@ fn reportRetryableCObjectError(...@@ -2241,7 +2464,33 @@ fn reportRetryableCObjectError(
2241 }2464 }
2242}2465}
22432466
2244fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *std.Progress.Node) !void {2467fn reportRetryableAstGenError(
2468 comp: *Compilation,
2469 file: *Module.Scope.File,
2470 err: anyerror,
2471) error{OutOfMemory}!void {
2472 const mod = comp.bin_file.options.module.?;
2473 const gpa = mod.gpa;
2474
2475 file.status = .retryable_failure;
2476
2477 const err_msg = try Module.ErrorMsg.create(gpa, .{
2478 .file_scope = file,
2479 .parent_decl_node = 0,
2480 .lazy = .entire_file,
2481 }, "unable to load {s}: {s}", .{
2482 file.sub_file_path, @errorName(err),
2483 });
2484 errdefer err_msg.destroy(gpa);
2485
2486 {
2487 const lock = comp.mutex.acquire();
2488 defer lock.release();
2489 try mod.failed_files.putNoClobber(gpa, file, err_msg);
2490 }
2491}
2492
2493fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.Progress.Node) !void {
2245 if (!build_options.have_llvm) {2494 if (!build_options.have_llvm) {
2246 return comp.failCObj(c_object, "clang not available: compiler built without LLVM extensions", .{});2495 return comp.failCObj(c_object, "clang not available: compiler built without LLVM extensions", .{});
2247 }2496 }
...@@ -2292,8 +2541,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *...@@ -2292,8 +2541,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *
22922541
2293 const c_source_basename = std.fs.path.basename(c_object.src.src_path);2542 const c_source_basename = std.fs.path.basename(c_object.src.src_path);
22942543
2295 c_comp_progress_node.activate();2544 c_obj_prog_node.activate();
2296 var child_progress_node = c_comp_progress_node.start(c_source_basename, 0);2545 var child_progress_node = c_obj_prog_node.start(c_source_basename, 0);
2297 child_progress_node.activate();2546 child_progress_node.activate();
2298 defer child_progress_node.end();2547 defer child_progress_node.end();
22992548
...@@ -3009,7 +3258,8 @@ fn wantBuildLibCFromSource(comp: Compilation) bool {...@@ -3009,7 +3258,8 @@ fn wantBuildLibCFromSource(comp: Compilation) bool {
3009 .Exe => true,3258 .Exe => true,
3010 };3259 };
3011 return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and3260 return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and
3012 comp.bin_file.options.libc_installation == null;3261 comp.bin_file.options.libc_installation == null and
3262 comp.bin_file.options.object_format != .c;
3013}3263}
30143264
3015fn wantBuildGLibCFromSource(comp: Compilation) bool {3265fn wantBuildGLibCFromSource(comp: Compilation) bool {
...@@ -3031,7 +3281,8 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {...@@ -3031,7 +3281,8 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
3031 .Lib => comp.bin_file.options.link_mode == .Dynamic,3281 .Lib => comp.bin_file.options.link_mode == .Dynamic,
3032 .Exe => true,3282 .Exe => true,
3033 };3283 };
3034 return is_exe_or_dyn_lib and comp.bin_file.options.link_libunwind;3284 return is_exe_or_dyn_lib and comp.bin_file.options.link_libunwind and
3285 comp.bin_file.options.object_format != .c;
3035}3286}
30363287
3037fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) Allocator.Error!void {3288fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) Allocator.Error!void {
...@@ -3082,30 +3333,29 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc...@@ -3082,30 +3333,29 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc
30823333
3083 @setEvalBranchQuota(4000);3334 @setEvalBranchQuota(4000);
3084 try buffer.writer().print(3335 try buffer.writer().print(
3085 \\usingnamespace @import("std").builtin;3336 \\const std = @import("std");
3086 \\/// Deprecated
3087 \\pub const arch = Target.current.cpu.arch;
3088 \\/// Deprecated
3089 \\pub const endian = Target.current.cpu.arch.endian();
3090 \\
3091 \\/// Zig version. When writing code that supports multiple versions of Zig, prefer3337 \\/// Zig version. When writing code that supports multiple versions of Zig, prefer
3092 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.3338 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
3093 \\pub const zig_version = try @import("std").SemanticVersion.parse("{s}");3339 \\pub const zig_version = std.SemanticVersion.parse("{s}") catch unreachable;
3340 \\/// Temporary until self-hosted is feature complete.
3094 \\pub const zig_is_stage2 = {};3341 \\pub const zig_is_stage2 = {};
3342 \\/// Temporary until self-hosted supports the `cpu.arch` value.
3343 \\pub const stage2_arch: std.Target.Cpu.Arch = .{};
3095 \\3344 \\
3096 \\pub const output_mode = OutputMode.{};3345 \\pub const output_mode = std.builtin.OutputMode.{};
3097 \\pub const link_mode = LinkMode.{};3346 \\pub const link_mode = std.builtin.LinkMode.{};
3098 \\pub const is_test = {};3347 \\pub const is_test = {};
3099 \\pub const single_threaded = {};3348 \\pub const single_threaded = {};
3100 \\pub const abi = Abi.{};3349 \\pub const abi = std.Target.Abi.{};
3101 \\pub const cpu: Cpu = Cpu{{3350 \\pub const cpu: std.Target.Cpu = .{{
3102 \\ .arch = .{},3351 \\ .arch = .{},
3103 \\ .model = &Target.{}.cpu.{},3352 \\ .model = &std.Target.{}.cpu.{},
3104 \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{3353 \\ .features = std.Target.{}.featureSet(&[_]std.Target.{}.Feature{{
3105 \\3354 \\
3106 , .{3355 , .{
3107 build_options.version,3356 build_options.version,
3108 !use_stage1,3357 !use_stage1,
3358 std.zig.fmtId(@tagName(target.cpu.arch)),
3109 std.zig.fmtId(@tagName(comp.bin_file.options.output_mode)),3359 std.zig.fmtId(@tagName(comp.bin_file.options.output_mode)),
3110 std.zig.fmtId(@tagName(comp.bin_file.options.link_mode)),3360 std.zig.fmtId(@tagName(comp.bin_file.options.link_mode)),
3111 comp.bin_file.options.is_test,3361 comp.bin_file.options.is_test,
...@@ -3129,7 +3379,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc...@@ -3129,7 +3379,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc
3129 try buffer.writer().print(3379 try buffer.writer().print(
3130 \\ }}),3380 \\ }}),
3131 \\}};3381 \\}};
3132 \\pub const os = Os{{3382 \\pub const os = std.Target.Os{{
3133 \\ .tag = .{},3383 \\ .tag = .{},
3134 \\ .version_range = .{{3384 \\ .version_range = .{{
3135 ,3385 ,
...@@ -3216,8 +3466,13 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc...@@ -3216,8 +3466,13 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc
3216 (comp.bin_file.options.skip_linker_dependencies and comp.bin_file.options.parent_compilation_link_libc);3466 (comp.bin_file.options.skip_linker_dependencies and comp.bin_file.options.parent_compilation_link_libc);
32173467
3218 try buffer.writer().print(3468 try buffer.writer().print(
3219 \\pub const object_format = ObjectFormat.{};3469 \\pub const target = std.Target{{
3220 \\pub const mode = Mode.{};3470 \\ .cpu = cpu,
3471 \\ .os = os,
3472 \\ .abi = abi,
3473 \\}};
3474 \\pub const object_format = std.Target.ObjectFormat.{};
3475 \\pub const mode = std.builtin.Mode.{};
3221 \\pub const link_libc = {};3476 \\pub const link_libc = {};
3222 \\pub const link_libcpp = {};3477 \\pub const link_libcpp = {};
3223 \\pub const have_error_return_tracing = {};3478 \\pub const have_error_return_tracing = {};
...@@ -3225,7 +3480,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc...@@ -3225,7 +3480,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc
3225 \\pub const position_independent_code = {};3480 \\pub const position_independent_code = {};
3226 \\pub const position_independent_executable = {};3481 \\pub const position_independent_executable = {};
3227 \\pub const strip_debug_info = {};3482 \\pub const strip_debug_info = {};
3228 \\pub const code_model = CodeModel.{};3483 \\pub const code_model = std.builtin.CodeModel.{};
3229 \\3484 \\
3230 , .{3485 , .{
3231 std.zig.fmtId(@tagName(comp.bin_file.options.object_format)),3486 std.zig.fmtId(@tagName(comp.bin_file.options.object_format)),
...@@ -3242,7 +3497,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc...@@ -3242,7 +3497,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc
32423497
3243 if (comp.bin_file.options.is_test) {3498 if (comp.bin_file.options.is_test) {
3244 try buffer.appendSlice(3499 try buffer.appendSlice(
3245 \\pub var test_functions: []TestFn = undefined; // overwritten later3500 \\pub var test_functions: []std.builtin.TestFn = undefined; // overwritten later
3246 \\3501 \\
3247 );3502 );
3248 if (comp.test_evented_io) {3503 if (comp.test_evented_io) {
...@@ -3316,7 +3571,6 @@ fn buildOutputFromZig(...@@ -3316,7 +3571,6 @@ fn buildOutputFromZig(
3316 .handle = special_dir,3571 .handle = special_dir,
3317 },3572 },
3318 .root_src_path = src_basename,3573 .root_src_path = src_basename,
3319 .namespace_hash = Package.root_namespace_hash,
3320 };3574 };
3321 const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];3575 const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];
3322 const target = comp.getTarget();3576 const target = comp.getTarget();
...@@ -3445,7 +3699,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node...@@ -3445,7 +3699,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
3445 man.hash.add(comp.bin_file.options.emit != null);3699 man.hash.add(comp.bin_file.options.emit != null);
3446 man.hash.add(mod.emit_h != null);3700 man.hash.add(mod.emit_h != null);
3447 if (mod.emit_h) |emit_h| {3701 if (mod.emit_h) |emit_h| {
3448 man.hash.addEmitLoc(emit_h);3702 man.hash.addEmitLoc(emit_h.loc);
3449 }3703 }
3450 man.hash.addOptionalEmitLoc(comp.emit_asm);3704 man.hash.addOptionalEmitLoc(comp.emit_asm);
3451 man.hash.addOptionalEmitLoc(comp.emit_llvm_ir);3705 man.hash.addOptionalEmitLoc(comp.emit_llvm_ir);
...@@ -3564,7 +3818,8 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node...@@ -3564,7 +3818,8 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
3564 if (mod.emit_h != null) {3818 if (mod.emit_h != null) {
3565 log.warn("-femit-h is not available in the stage1 backend; no .h file will be produced", .{});3819 log.warn("-femit-h is not available in the stage1 backend; no .h file will be produced", .{});
3566 }3820 }
3567 const emit_h_path = try stage1LocPath(arena, mod.emit_h, directory);3821 const emit_h_loc: ?EmitLoc = if (mod.emit_h) |emit_h| emit_h.loc else null;
3822 const emit_h_path = try stage1LocPath(arena, emit_h_loc, directory);
3568 const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory);3823 const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory);
3569 const emit_llvm_ir_path = try stage1LocPath(arena, comp.emit_llvm_ir, directory);3824 const emit_llvm_ir_path = try stage1LocPath(arena, comp.emit_llvm_ir, directory);
3570 const emit_analysis_path = try stage1LocPath(arena, comp.emit_analysis, directory);3825 const emit_analysis_path = try stage1LocPath(arena, comp.emit_analysis, directory);
src/Module.zig+2576-2403
...@@ -15,13 +15,14 @@ const ast = std.zig.ast;...@@ -15,13 +15,14 @@ const ast = std.zig.ast;
1515
16const Module = @This();16const Module = @This();
17const Compilation = @import("Compilation.zig");17const Compilation = @import("Compilation.zig");
18const Cache = @import("Cache.zig");
18const Value = @import("value.zig").Value;19const Value = @import("value.zig").Value;
19const Type = @import("type.zig").Type;20const Type = @import("type.zig").Type;
20const TypedValue = @import("TypedValue.zig");21const TypedValue = @import("TypedValue.zig");
21const Package = @import("Package.zig");22const Package = @import("Package.zig");
22const link = @import("link.zig");23const link = @import("link.zig");
23const ir = @import("ir.zig");24const ir = @import("ir.zig");
24const zir = @import("zir.zig");25const Zir = @import("Zir.zig");
25const trace = @import("tracy.zig").trace;26const trace = @import("tracy.zig").trace;
26const AstGen = @import("AstGen.zig");27const AstGen = @import("AstGen.zig");
27const Sema = @import("Sema.zig");28const Sema = @import("Sema.zig");
...@@ -35,38 +36,39 @@ comp: *Compilation,...@@ -35,38 +36,39 @@ comp: *Compilation,
35zig_cache_artifact_directory: Compilation.Directory,36zig_cache_artifact_directory: Compilation.Directory,
36/// Pointer to externally managed resource. `null` if there is no zig file being compiled.37/// Pointer to externally managed resource. `null` if there is no zig file being compiled.
37root_pkg: *Package,38root_pkg: *Package,
38/// Module owns this resource.39
39root_scope: *Scope.File,40/// Used by AstGen worker to load and store ZIR cache.
40/// It's rare for a decl to be exported, so we save memory by having a sparse map of41global_zir_cache: Compilation.Directory,
41/// Decl pointers to details about them being exported.42/// Used by AstGen worker to load and store ZIR cache.
42/// The Export memory is owned by the `export_owners` table; the slice itself is owned by this table.43local_zir_cache: Compilation.Directory,
43/// The slice is guaranteed to not be empty.44/// It's rare for a decl to be exported, so we save memory by having a sparse
45/// map of Decl pointers to details about them being exported.
46/// The Export memory is owned by the `export_owners` table; the slice itself
47/// is owned by this table. The slice is guaranteed to not be empty.
44decl_exports: std.AutoArrayHashMapUnmanaged(*Decl, []*Export) = .{},48decl_exports: std.AutoArrayHashMapUnmanaged(*Decl, []*Export) = .{},
45/// We track which export is associated with the given symbol name for quick
46/// detection of symbol collisions.
47symbol_exports: std.StringArrayHashMapUnmanaged(*Export) = .{},
48/// This models the Decls that perform exports, so that `decl_exports` can be updated when a Decl49/// This models the Decls that perform exports, so that `decl_exports` can be updated when a Decl
49/// is modified. Note that the key of this table is not the Decl being exported, but the Decl that50/// is modified. Note that the key of this table is not the Decl being exported, but the Decl that
50/// is performing the export of another Decl.51/// is performing the export of another Decl.
51/// This table owns the Export memory.52/// This table owns the Export memory.
52export_owners: std.AutoArrayHashMapUnmanaged(*Decl, []*Export) = .{},53export_owners: std.AutoArrayHashMapUnmanaged(*Decl, []*Export) = .{},
53/// Maps fully qualified namespaced names to the Decl struct for them.54/// The set of all the files in the Module. We keep track of this in order to iterate
54decl_table: std.ArrayHashMapUnmanaged(Scope.NameHash, *Decl, Scope.name_hash_hash, Scope.name_hash_eql, false) = .{},55/// over it and check which source files have been modified on the file system when
56/// an update is requested, as well as to cache `@import` results.
57/// Keys are fully resolved file paths. This table owns the keys and values.
58import_table: std.StringArrayHashMapUnmanaged(*Scope.File) = .{},
59
55/// We optimize memory usage for a compilation with no compile errors by storing the60/// We optimize memory usage for a compilation with no compile errors by storing the
56/// error messages and mapping outside of `Decl`.61/// error messages and mapping outside of `Decl`.
57/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.62/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.
58/// Note that a Decl can succeed but the Fn it represents can fail. In this case,63/// Note that a Decl can succeed but the Fn it represents can fail. In this case,
59/// a Decl can have a failed_decls entry but have analysis status of success.64/// a Decl can have a failed_decls entry but have analysis status of success.
60failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *ErrorMsg) = .{},65failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *ErrorMsg) = .{},
61/// When emit_h is non-null, each Decl gets one more compile error slot for
62/// emit-h failing for that Decl. This table is also how we tell if a Decl has
63/// failed emit-h or succeeded.
64emit_h_failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *ErrorMsg) = .{},
65/// Keep track of one `@compileLog` callsite per owner Decl.66/// Keep track of one `@compileLog` callsite per owner Decl.
66compile_log_decls: std.AutoArrayHashMapUnmanaged(*Decl, SrcLoc) = .{},67/// The value is the AST node index offset from the Decl.
68compile_log_decls: std.AutoArrayHashMapUnmanaged(*Decl, i32) = .{},
67/// Using a map here for consistency with the other fields here.69/// Using a map here for consistency with the other fields here.
68/// The ErrorMsg memory is owned by the `Scope.File`, using Module's general purpose allocator.70/// The ErrorMsg memory is owned by the `Scope.File`, using Module's general purpose allocator.
69failed_files: std.AutoArrayHashMapUnmanaged(*Scope.File, *ErrorMsg) = .{},71failed_files: std.AutoArrayHashMapUnmanaged(*Scope.File, ?*ErrorMsg) = .{},
70/// Using a map here for consistency with the other fields here.72/// Using a map here for consistency with the other fields here.
71/// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.73/// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.
72failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{},74failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{},
...@@ -85,17 +87,11 @@ global_error_set: std.StringHashMapUnmanaged(ErrorInt) = .{},...@@ -85,17 +87,11 @@ global_error_set: std.StringHashMapUnmanaged(ErrorInt) = .{},
85/// Corresponds with `global_error_set`.87/// Corresponds with `global_error_set`.
86error_name_list: ArrayListUnmanaged([]const u8) = .{},88error_name_list: ArrayListUnmanaged([]const u8) = .{},
8789
88/// Keys are fully qualified paths
89import_table: std.StringArrayHashMapUnmanaged(*Scope.File) = .{},
90
91/// Incrementing integer used to compare against the corresponding Decl90/// Incrementing integer used to compare against the corresponding Decl
92/// field to determine whether a Decl's status applies to an ongoing update, or a91/// field to determine whether a Decl's status applies to an ongoing update, or a
93/// previous analysis.92/// previous analysis.
94generation: u32 = 0,93generation: u32 = 0,
9594
96/// When populated it means there was an error opening/reading the root source file.
97failed_root_src_file: ?anyerror = null,
98
99stage1_flags: packed struct {95stage1_flags: packed struct {
100 have_winmain: bool = false,96 have_winmain: bool = false,
101 have_wwinmain: bool = false,97 have_wwinmain: bool = false,
...@@ -106,10 +102,24 @@ stage1_flags: packed struct {...@@ -106,10 +102,24 @@ stage1_flags: packed struct {
106 reserved: u2 = 0,102 reserved: u2 = 0,
107} = .{},103} = .{},
108104
109emit_h: ?Compilation.EmitLoc,105job_queued_update_builtin_zig: bool = true,
110106
111compile_log_text: ArrayListUnmanaged(u8) = .{},107compile_log_text: ArrayListUnmanaged(u8) = .{},
112108
109emit_h: ?*GlobalEmitH,
110
111/// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.
112pub const GlobalEmitH = struct {
113 /// Where to put the output.
114 loc: Compilation.EmitLoc,
115 /// When emit_h is non-null, each Decl gets one more compile error slot for
116 /// emit-h failing for that Decl. This table is also how we tell if a Decl has
117 /// failed emit-h or succeeded.
118 failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *ErrorMsg) = .{},
119 /// Tracks all decls in order to iterate over them and emit .h code for them.
120 decl_table: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
121};
122
113pub const ErrorInt = u32;123pub const ErrorInt = u32;
114124
115pub const Export = struct {125pub const Export = struct {
...@@ -129,6 +139,14 @@ pub const Export = struct {...@@ -129,6 +139,14 @@ pub const Export = struct {
129 failed_retryable,139 failed_retryable,
130 complete,140 complete,
131 },141 },
142
143 pub fn getSrcLoc(exp: Export) SrcLoc {
144 return .{
145 .file_scope = exp.owner_decl.namespace.file_scope,
146 .parent_decl_node = exp.owner_decl.src_node,
147 .lazy = exp.src,
148 };
149 }
132};150};
133151
134/// When Module emit_h field is non-null, each Decl is allocated via this struct, so that152/// When Module emit_h field is non-null, each Decl is allocated via this struct, so that
...@@ -139,31 +157,43 @@ pub const DeclPlusEmitH = struct {...@@ -139,31 +157,43 @@ pub const DeclPlusEmitH = struct {
139};157};
140158
141pub const Decl = struct {159pub const Decl = struct {
142 /// This name is relative to the containing namespace of the decl. It uses160 /// Allocated with Module's allocator; outlives the ZIR code.
143 /// null-termination to save bytes, since there can be a lot of decls in a
144 /// compilation. The null byte is not allowed in symbol names, because
145 /// executable file formats use null-terminated strings for symbol names.
146 /// All Decls have names, even values that are not bound to a zig namespace.
147 /// This is necessary for mapping them to an address in the output file.
148 /// Memory owned by this decl, using Module's allocator.
149 name: [*:0]const u8,161 name: [*:0]const u8,
150 /// The direct parent container of the Decl.162 /// The most recent Type of the Decl after a successful semantic analysis.
163 /// Populated when `has_tv`.
164 ty: Type,
165 /// The most recent Value of the Decl after a successful semantic analysis.
166 /// Populated when `has_tv`.
167 val: Value,
168 /// Populated when `has_tv`.
169 align_val: Value,
170 /// Populated when `has_tv`.
171 linksection_val: Value,
172 /// The memory for ty, val, align_val, linksection_val.
173 /// If this is `null` then there is no memory management needed.
174 value_arena: ?*std.heap.ArenaAllocator.State = null,
175 /// The direct parent namespace of the Decl.
151 /// Reference to externally owned memory.176 /// Reference to externally owned memory.
152 container: *Scope.Container,177 /// In the case of the Decl corresponding to a file, this is
178 /// the namespace of the struct, since there is no parent.
179 namespace: *Scope.Namespace,
153180
154 /// An integer that can be checked against the corresponding incrementing181 /// An integer that can be checked against the corresponding incrementing
155 /// generation field of Module. This is used to determine whether `complete` status182 /// generation field of Module. This is used to determine whether `complete` status
156 /// represents pre- or post- re-analysis.183 /// represents pre- or post- re-analysis.
157 generation: u32,184 generation: u32,
158 /// The AST Node index or ZIR Inst index that contains this declaration.185 /// The AST node index of this declaration.
159 /// Must be recomputed when the corresponding source file is modified.186 /// Must be recomputed when the corresponding source file is modified.
160 src_node: ast.Node.Index,187 src_node: ast.Node.Index,
188 /// Line number corresponding to `src_node`. Stored separately so that source files
189 /// do not need to be loaded into memory in order to compute debug line numbers.
190 src_line: u32,
191 /// Index to ZIR `extra` array to the entry in the parent's decl structure
192 /// (the part that says "for every decls_len"). The first item at this index is
193 /// the contents hash, followed by line, name, etc.
194 /// For anonymous decls and also the root Decl for a File, this is 0.
195 zir_decl_index: Zir.Inst.Index,
161196
162 /// The most recent value of the Decl after a successful semantic analysis.
163 typed_value: union(enum) {
164 never_succeeded: void,
165 most_recent: TypedValue.Managed,
166 },
167 /// Represents the "shallow" analysis status. For example, for decls that are functions,197 /// Represents the "shallow" analysis status. For example, for decls that are functions,
168 /// the function type is analyzed with this set to `in_progress`, however, the semantic198 /// the function type is analyzed with this set to `in_progress`, however, the semantic
169 /// analysis of the function body is performed with this value set to `success`. Functions199 /// analysis of the function body is performed with this value set to `success`. Functions
...@@ -172,8 +202,12 @@ pub const Decl = struct {...@@ -172,8 +202,12 @@ pub const Decl = struct {
172 /// This Decl corresponds to an AST Node that has not been referenced yet, and therefore202 /// This Decl corresponds to an AST Node that has not been referenced yet, and therefore
173 /// because of Zig's lazy declaration analysis, it will remain unanalyzed until referenced.203 /// because of Zig's lazy declaration analysis, it will remain unanalyzed until referenced.
174 unreferenced,204 unreferenced,
175 /// Semantic analysis for this Decl is running right now. This state detects dependency loops.205 /// Semantic analysis for this Decl is running right now.
206 /// This state detects dependency loops.
176 in_progress,207 in_progress,
208 /// The file corresponding to this Decl had a parse error or ZIR error.
209 /// There will be a corresponding ErrorMsg in Module.failed_files.
210 file_failure,
177 /// This Decl might be OK but it depends on another one which did not successfully complete211 /// This Decl might be OK but it depends on another one which did not successfully complete
178 /// semantic analysis.212 /// semantic analysis.
179 dependency_failure,213 dependency_failure,
...@@ -198,11 +232,23 @@ pub const Decl = struct {...@@ -198,11 +232,23 @@ pub const Decl = struct {
198 /// to require re-analysis.232 /// to require re-analysis.
199 outdated,233 outdated,
200 },234 },
235 /// Whether `typed_value`, `align_val`, and `linksection_val` are populated.
236 has_tv: bool,
237 /// If `true` it means the `Decl` is the resource owner of the type/value associated
238 /// with it. That means when `Decl` is destroyed, the cleanup code should additionally
239 /// check if the value owns a `Namespace`, and destroy that too.
240 owns_tv: bool,
201 /// This flag is set when this Decl is added to `Module.deletion_set`, and cleared241 /// This flag is set when this Decl is added to `Module.deletion_set`, and cleared
202 /// when removed.242 /// when removed.
203 deletion_flag: bool,243 deletion_flag: bool,
204 /// Whether the corresponding AST decl has a `pub` keyword.244 /// Whether the corresponding AST decl has a `pub` keyword.
205 is_pub: bool,245 is_pub: bool,
246 /// Whether the corresponding AST decl has a `export` keyword.
247 is_exported: bool,
248 /// Whether the ZIR code provides an align instruction.
249 has_align: bool,
250 /// Whether the ZIR code provides a linksection instruction.
251 has_linksection: bool,
206252
207 /// Represents the position of the code in the output file.253 /// Represents the position of the code in the output file.
208 /// This is populated regardless of semantic analysis and code generation.254 /// This is populated regardless of semantic analysis and code generation.
...@@ -215,8 +261,6 @@ pub const Decl = struct {...@@ -215,8 +261,6 @@ pub const Decl = struct {
215 /// to save on memory usage.261 /// to save on memory usage.
216 fn_link: link.File.LinkFn,262 fn_link: link.File.LinkFn,
217263
218 contents_hash: std.zig.SrcHash,
219
220 /// The shallow set of other decls whose typed_value could possibly change if this Decl's264 /// The shallow set of other decls whose typed_value could possibly change if this Decl's
221 /// typed_value is modified.265 /// typed_value is modified.
222 dependants: DepsTable = .{},266 dependants: DepsTable = .{},
...@@ -226,20 +270,34 @@ pub const Decl = struct {...@@ -226,20 +270,34 @@ pub const Decl = struct {
226270
227 /// The reason this is not `std.AutoArrayHashMapUnmanaged` is a workaround for271 /// The reason this is not `std.AutoArrayHashMapUnmanaged` is a workaround for
228 /// stage1 compiler giving me: `error: struct 'Module.Decl' depends on itself`272 /// stage1 compiler giving me: `error: struct 'Module.Decl' depends on itself`
229 pub const DepsTable = std.ArrayHashMapUnmanaged(*Decl, void, std.array_hash_map.getAutoHashFn(*Decl), std.array_hash_map.getAutoEqlFn(*Decl), false);273 pub const DepsTable = std.ArrayHashMapUnmanaged(
274 *Decl,
275 void,
276 std.array_hash_map.getAutoHashFn(*Decl),
277 std.array_hash_map.getAutoEqlFn(*Decl),
278 false,
279 );
280
281 pub fn clearName(decl: *Decl, gpa: *Allocator) void {
282 gpa.free(mem.spanZ(decl.name));
283 decl.name = undefined;
284 }
230285
231 pub fn destroy(decl: *Decl, module: *Module) void {286 pub fn destroy(decl: *Decl, module: *Module) void {
232 const gpa = module.gpa;287 const gpa = module.gpa;
233 gpa.free(mem.spanZ(decl.name));288 log.debug("destroy {*} ({s})", .{ decl, decl.name });
234 if (decl.typedValueManaged()) |tvm| {289 if (decl.deletion_flag) {
235 if (tvm.typed_value.val.castTag(.function)) |payload| {290 module.deletion_set.swapRemoveAssertDiscard(decl);
236 const func = payload.data;291 }
237 func.deinit(gpa);292 if (decl.has_tv) {
293 if (decl.getInnerNamespace()) |namespace| {
294 namespace.destroyDecls(module);
238 }295 }
239 tvm.deinit(gpa);296 decl.clearValues(gpa);
240 }297 }
241 decl.dependants.deinit(gpa);298 decl.dependants.deinit(gpa);
242 decl.dependencies.deinit(gpa);299 decl.dependencies.deinit(gpa);
300 decl.clearName(gpa);
243 if (module.emit_h != null) {301 if (module.emit_h != null) {
244 const decl_plus_emit_h = @fieldParentPtr(DeclPlusEmitH, "decl", decl);302 const decl_plus_emit_h = @fieldParentPtr(DeclPlusEmitH, "decl", decl);
245 decl_plus_emit_h.emit_h.fwd_decl.deinit(gpa);303 decl_plus_emit_h.emit_h.fwd_decl.deinit(gpa);
...@@ -249,6 +307,87 @@ pub const Decl = struct {...@@ -249,6 +307,87 @@ pub const Decl = struct {
249 }307 }
250 }308 }
251309
310 pub fn clearValues(decl: *Decl, gpa: *Allocator) void {
311 if (decl.getFunction()) |func| {
312 func.deinit(gpa);
313 gpa.destroy(func);
314 }
315 if (decl.getVariable()) |variable| {
316 gpa.destroy(variable);
317 }
318 if (decl.value_arena) |arena_state| {
319 arena_state.promote(gpa).deinit();
320 decl.value_arena = null;
321 decl.has_tv = false;
322 decl.owns_tv = false;
323 }
324 }
325
326 pub fn finalizeNewArena(decl: *Decl, arena: *std.heap.ArenaAllocator) !void {
327 assert(decl.value_arena == null);
328 const arena_state = try arena.allocator.create(std.heap.ArenaAllocator.State);
329 arena_state.* = arena.state;
330 decl.value_arena = arena_state;
331 }
332
333 /// This name is relative to the containing namespace of the decl.
334 /// The memory is owned by the containing File ZIR.
335 pub fn getName(decl: Decl) ?[:0]const u8 {
336 const zir = decl.namespace.file_scope.zir;
337 return decl.getNameZir(zir);
338 }
339
340 pub fn getNameZir(decl: Decl, zir: Zir) ?[:0]const u8 {
341 assert(decl.zir_decl_index != 0);
342 const name_index = zir.extra[decl.zir_decl_index + 5];
343 if (name_index <= 1) return null;
344 return zir.nullTerminatedString(name_index);
345 }
346
347 pub fn contentsHash(decl: Decl) std.zig.SrcHash {
348 const zir = decl.namespace.file_scope.zir;
349 return decl.contentsHashZir(zir);
350 }
351
352 pub fn contentsHashZir(decl: Decl, zir: Zir) std.zig.SrcHash {
353 assert(decl.zir_decl_index != 0);
354 const hash_u32s = zir.extra[decl.zir_decl_index..][0..4];
355 const contents_hash = @bitCast(std.zig.SrcHash, hash_u32s.*);
356 return contents_hash;
357 }
358
359 pub fn zirBlockIndex(decl: *const Decl) Zir.Inst.Index {
360 assert(decl.zir_decl_index != 0);
361 const zir = decl.namespace.file_scope.zir;
362 return zir.extra[decl.zir_decl_index + 6];
363 }
364
365 pub fn zirAlignRef(decl: Decl) Zir.Inst.Ref {
366 if (!decl.has_align) return .none;
367 assert(decl.zir_decl_index != 0);
368 const zir = decl.namespace.file_scope.zir;
369 return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 6]);
370 }
371
372 pub fn zirLinksectionRef(decl: Decl) Zir.Inst.Ref {
373 if (!decl.has_linksection) return .none;
374 assert(decl.zir_decl_index != 0);
375 const zir = decl.namespace.file_scope.zir;
376 const extra_index = decl.zir_decl_index + 6 + @boolToInt(decl.has_align);
377 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
378 }
379
380 /// Returns true if and only if the Decl is the top level struct associated with a File.
381 pub fn isRoot(decl: *const Decl) bool {
382 if (decl.namespace.parent != null)
383 return false;
384 return decl == decl.namespace.ty.getOwnerDecl();
385 }
386
387 pub fn relativeToLine(decl: Decl, offset: u32) u32 {
388 return decl.src_line + offset;
389 }
390
252 pub fn relativeToNodeIndex(decl: Decl, offset: i32) ast.Node.Index {391 pub fn relativeToNodeIndex(decl: Decl, offset: i32) ast.Node.Index {
253 return @bitCast(ast.Node.Index, offset + @bitCast(i32, decl.src_node));392 return @bitCast(ast.Node.Index, offset + @bitCast(i32, decl.src_node));
254 }393 }
...@@ -265,30 +404,31 @@ pub const Decl = struct {...@@ -265,30 +404,31 @@ pub const Decl = struct {
265 return .{ .node_offset = decl.nodeIndexToRelative(node_index) };404 return .{ .node_offset = decl.nodeIndexToRelative(node_index) };
266 }405 }
267406
268 pub fn srcLoc(decl: *Decl) SrcLoc {407 pub fn srcLoc(decl: Decl) SrcLoc {
408 return decl.nodeOffsetSrcLoc(0);
409 }
410
411 pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32) SrcLoc {
269 return .{412 return .{
270 .container = .{ .decl = decl },413 .file_scope = decl.getFileScope(),
271 .lazy = .{ .node_offset = 0 },414 .parent_decl_node = decl.src_node,
415 .lazy = .{ .node_offset = node_offset },
272 };416 };
273 }417 }
274418
275 pub fn srcToken(decl: Decl) u32 {419 pub fn srcToken(decl: Decl) ast.TokenIndex {
276 const tree = &decl.container.file_scope.tree;420 const tree = &decl.namespace.file_scope.tree;
277 return tree.firstToken(decl.src_node);421 return tree.firstToken(decl.src_node);
278 }422 }
279423
280 pub fn srcByteOffset(decl: Decl) u32 {424 pub fn srcByteOffset(decl: Decl) u32 {
281 const tree = &decl.container.file_scope.tree;425 const tree = &decl.namespace.file_scope.tree;
282 return tree.tokens.items(.start)[decl.srcToken()];426 return tree.tokens.items(.start)[decl.srcToken()];
283 }427 }
284428
285 pub fn fullyQualifiedNameHash(decl: Decl) Scope.NameHash {
286 return decl.container.fullyQualifiedNameHash(mem.spanZ(decl.name));
287 }
288
289 pub fn renderFullyQualifiedName(decl: Decl, writer: anytype) !void {429 pub fn renderFullyQualifiedName(decl: Decl, writer: anytype) !void {
290 const unqualified_name = mem.spanZ(decl.name);430 const unqualified_name = mem.spanZ(decl.name);
291 return decl.container.renderFullyQualifiedName(unqualified_name, writer);431 return decl.namespace.renderFullyQualifiedName(unqualified_name, writer);
292 }432 }
293433
294 pub fn getFullyQualifiedName(decl: Decl, gpa: *Allocator) ![]u8 {434 pub fn getFullyQualifiedName(decl: Decl, gpa: *Allocator) ![]u8 {
...@@ -298,15 +438,92 @@ pub const Decl = struct {...@@ -298,15 +438,92 @@ pub const Decl = struct {
298 return buffer.toOwnedSlice();438 return buffer.toOwnedSlice();
299 }439 }
300440
301 pub fn typedValue(decl: *Decl) error{AnalysisFail}!TypedValue {441 pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue {
302 const tvm = decl.typedValueManaged() orelse return error.AnalysisFail;442 if (!decl.has_tv) return error.AnalysisFail;
303 return tvm.typed_value;443 return TypedValue{
444 .ty = decl.ty,
445 .val = decl.val,
446 };
304 }447 }
305448
306 pub fn value(decl: *Decl) error{AnalysisFail}!Value {449 pub fn value(decl: *Decl) error{AnalysisFail}!Value {
307 return (try decl.typedValue()).val;450 return (try decl.typedValue()).val;
308 }451 }
309452
453 pub fn isFunction(decl: *Decl) !bool {
454 const tv = try decl.typedValue();
455 return tv.ty.zigTypeTag() == .Fn;
456 }
457
458 /// If the Decl has a value and it is a struct, return it,
459 /// otherwise null.
460 pub fn getStruct(decl: *Decl) ?*Struct {
461 if (!decl.owns_tv) return null;
462 const ty = (decl.val.castTag(.ty) orelse return null).data;
463 const struct_obj = (ty.castTag(.@"struct") orelse return null).data;
464 assert(struct_obj.owner_decl == decl);
465 return struct_obj;
466 }
467
468 /// If the Decl has a value and it is a union, return it,
469 /// otherwise null.
470 pub fn getUnion(decl: *Decl) ?*Union {
471 if (!decl.owns_tv) return null;
472 const ty = (decl.val.castTag(.ty) orelse return null).data;
473 const union_obj = (ty.cast(Type.Payload.Union) orelse return null).data;
474 assert(union_obj.owner_decl == decl);
475 return union_obj;
476 }
477
478 /// If the Decl has a value and it is a function, return it,
479 /// otherwise null.
480 pub fn getFunction(decl: *Decl) ?*Fn {
481 if (!decl.owns_tv) return null;
482 const func = (decl.val.castTag(.function) orelse return null).data;
483 assert(func.owner_decl == decl);
484 return func;
485 }
486
487 pub fn getVariable(decl: *Decl) ?*Var {
488 if (!decl.owns_tv) return null;
489 const variable = (decl.val.castTag(.variable) orelse return null).data;
490 assert(variable.owner_decl == decl);
491 return variable;
492 }
493
494 /// Gets the namespace that this Decl creates by being a struct, union,
495 /// enum, or opaque.
496 /// Only returns it if the Decl is the owner.
497 pub fn getInnerNamespace(decl: *Decl) ?*Scope.Namespace {
498 if (!decl.owns_tv) return null;
499 const ty = (decl.val.castTag(.ty) orelse return null).data;
500 switch (ty.tag()) {
501 .@"struct" => {
502 const struct_obj = ty.castTag(.@"struct").?.data;
503 assert(struct_obj.owner_decl == decl);
504 return &struct_obj.namespace;
505 },
506 .enum_full => {
507 const enum_obj = ty.castTag(.enum_full).?.data;
508 assert(enum_obj.owner_decl == decl);
509 return &enum_obj.namespace;
510 },
511 .empty_struct => {
512 return ty.castTag(.empty_struct).?.data;
513 },
514 .@"opaque" => {
515 @panic("TODO opaque types");
516 },
517 .@"union", .union_tagged => {
518 const union_obj = ty.cast(Type.Payload.Union).?.data;
519 assert(union_obj.owner_decl == decl);
520 return &union_obj.namespace;
521 },
522
523 else => return null,
524 }
525 }
526
310 pub fn dump(decl: *Decl) void {527 pub fn dump(decl: *Decl) void {
311 const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src);528 const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src);
312 std.debug.print("{s}:{d}:{d} name={s} status={s}", .{529 std.debug.print("{s}:{d}:{d} name={s} status={s}", .{
...@@ -316,21 +533,14 @@ pub const Decl = struct {...@@ -316,21 +533,14 @@ pub const Decl = struct {
316 mem.spanZ(decl.name),533 mem.spanZ(decl.name),
317 @tagName(decl.analysis),534 @tagName(decl.analysis),
318 });535 });
319 if (decl.typedValueManaged()) |tvm| {536 if (decl.has_tv) {
320 std.debug.print(" ty={} val={}", .{ tvm.typed_value.ty, tvm.typed_value.val });537 std.debug.print(" ty={} val={}", .{ decl.ty, decl.val });
321 }538 }
322 std.debug.print("\n", .{});539 std.debug.print("\n", .{});
323 }540 }
324541
325 pub fn typedValueManaged(decl: *Decl) ?*TypedValue.Managed {
326 switch (decl.typed_value) {
327 .most_recent => |*x| return x,
328 .never_succeeded => return null,
329 }
330 }
331
332 pub fn getFileScope(decl: Decl) *Scope.File {542 pub fn getFileScope(decl: Decl) *Scope.File {
333 return decl.container.file_scope;543 return decl.namespace.file_scope;
334 }544 }
335545
336 pub fn getEmitH(decl: *Decl, module: *Module) *EmitH {546 pub fn getEmitH(decl: *Decl, module: *Module) *EmitH {
...@@ -355,17 +565,20 @@ pub const EmitH = struct {...@@ -355,17 +565,20 @@ pub const EmitH = struct {
355565
356/// Represents the data that an explicit error set syntax provides.566/// Represents the data that an explicit error set syntax provides.
357pub const ErrorSet = struct {567pub const ErrorSet = struct {
568 /// The Decl that corresponds to the error set itself.
358 owner_decl: *Decl,569 owner_decl: *Decl,
359 /// Offset from Decl node index, points to the error set AST node.570 /// Offset from Decl node index, points to the error set AST node.
360 node_offset: i32,571 node_offset: i32,
361 names_len: u32,572 names_len: u32,
362 /// The string bytes are stored in the owner Decl arena.573 /// The string bytes are stored in the owner Decl arena.
363 /// They are in the same order they appear in the AST.574 /// They are in the same order they appear in the AST.
575 /// The length is given by `names_len`.
364 names_ptr: [*]const []const u8,576 names_ptr: [*]const []const u8,
365577
366 pub fn srcLoc(self: ErrorSet) SrcLoc {578 pub fn srcLoc(self: ErrorSet) SrcLoc {
367 return .{579 return .{
368 .container = .{ .decl = self.owner_decl },580 .file_scope = self.owner_decl.getFileScope(),
581 .parent_decl_node = self.owner_decl.src_node,
369 .lazy = .{ .node_offset = self.node_offset },582 .lazy = .{ .node_offset = self.node_offset },
370 };583 };
371 }584 }
...@@ -373,20 +586,36 @@ pub const ErrorSet = struct {...@@ -373,20 +586,36 @@ pub const ErrorSet = struct {
373586
374/// Represents the data that a struct declaration provides.587/// Represents the data that a struct declaration provides.
375pub const Struct = struct {588pub const Struct = struct {
589 /// The Decl that corresponds to the struct itself.
376 owner_decl: *Decl,590 owner_decl: *Decl,
377 /// Set of field names in declaration order.591 /// Set of field names in declaration order.
378 fields: std.StringArrayHashMapUnmanaged(Field),592 fields: std.StringArrayHashMapUnmanaged(Field),
379 /// Represents the declarations inside this struct.593 /// Represents the declarations inside this struct.
380 container: Scope.Container,594 namespace: Scope.Namespace,
381
382 /// Offset from `owner_decl`, points to the struct AST node.595 /// Offset from `owner_decl`, points to the struct AST node.
383 node_offset: i32,596 node_offset: i32,
597 /// Index of the struct_decl ZIR instruction.
598 zir_index: Zir.Inst.Index,
599
600 layout: std.builtin.TypeInfo.ContainerLayout,
601 status: enum {
602 none,
603 field_types_wip,
604 have_field_types,
605 layout_wip,
606 have_layout,
607 },
384608
385 pub const Field = struct {609 pub const Field = struct {
610 /// Uses `noreturn` to indicate `anytype`.
611 /// undefined until `status` is `have_field_types` or `have_layout`.
386 ty: Type,612 ty: Type,
387 abi_align: Value,613 abi_align: Value,
388 /// Uses `unreachable_value` to indicate no default.614 /// Uses `unreachable_value` to indicate no default.
389 default_val: Value,615 default_val: Value,
616 /// undefined until `status` is `have_layout`.
617 offset: u32,
618 is_comptime: bool,
390 };619 };
391620
392 pub fn getFullyQualifiedName(s: *Struct, gpa: *Allocator) ![]u8 {621 pub fn getFullyQualifiedName(s: *Struct, gpa: *Allocator) ![]u8 {
...@@ -395,10 +624,23 @@ pub const Struct = struct {...@@ -395,10 +624,23 @@ pub const Struct = struct {
395624
396 pub fn srcLoc(s: Struct) SrcLoc {625 pub fn srcLoc(s: Struct) SrcLoc {
397 return .{626 return .{
398 .container = .{ .decl = s.owner_decl },627 .file_scope = s.owner_decl.getFileScope(),
628 .parent_decl_node = s.owner_decl.src_node,
399 .lazy = .{ .node_offset = s.node_offset },629 .lazy = .{ .node_offset = s.node_offset },
400 };630 };
401 }631 }
632
633 pub fn haveFieldTypes(s: Struct) bool {
634 return switch (s.status) {
635 .none,
636 .field_types_wip,
637 => false,
638 .have_field_types,
639 .layout_wip,
640 .have_layout,
641 => true,
642 };
643 }
402};644};
403645
404/// Represents the data that an enum declaration provides, when the fields646/// Represents the data that an enum declaration provides, when the fields
...@@ -406,6 +648,7 @@ pub const Struct = struct {...@@ -406,6 +648,7 @@ pub const Struct = struct {
406/// is inferred to be the smallest power of two unsigned int that fits648/// is inferred to be the smallest power of two unsigned int that fits
407/// the number of fields.649/// the number of fields.
408pub const EnumSimple = struct {650pub const EnumSimple = struct {
651 /// The Decl that corresponds to the enum itself.
409 owner_decl: *Decl,652 owner_decl: *Decl,
410 /// Set of field names in declaration order.653 /// Set of field names in declaration order.
411 fields: std.StringArrayHashMapUnmanaged(void),654 fields: std.StringArrayHashMapUnmanaged(void),
...@@ -414,7 +657,8 @@ pub const EnumSimple = struct {...@@ -414,7 +657,8 @@ pub const EnumSimple = struct {
414657
415 pub fn srcLoc(self: EnumSimple) SrcLoc {658 pub fn srcLoc(self: EnumSimple) SrcLoc {
416 return .{659 return .{
417 .container = .{ .decl = self.owner_decl },660 .file_scope = self.owner_decl.getFileScope(),
661 .parent_decl_node = self.owner_decl.src_node,
418 .lazy = .{ .node_offset = self.node_offset },662 .lazy = .{ .node_offset = self.node_offset },
419 };663 };
420 }664 }
...@@ -423,6 +667,7 @@ pub const EnumSimple = struct {...@@ -423,6 +667,7 @@ pub const EnumSimple = struct {
423/// Represents the data that an enum declaration provides, when there is667/// Represents the data that an enum declaration provides, when there is
424/// at least one tag value explicitly specified, or at least one declaration.668/// at least one tag value explicitly specified, or at least one declaration.
425pub const EnumFull = struct {669pub const EnumFull = struct {
670 /// The Decl that corresponds to the enum itself.
426 owner_decl: *Decl,671 owner_decl: *Decl,
427 /// An integer type which is used for the numerical value of the enum.672 /// An integer type which is used for the numerical value of the enum.
428 /// Whether zig chooses this type or the user specifies it, it is stored here.673 /// Whether zig chooses this type or the user specifies it, it is stored here.
...@@ -434,7 +679,7 @@ pub const EnumFull = struct {...@@ -434,7 +679,7 @@ pub const EnumFull = struct {
434 /// If this hash map is empty, it means the enum tags are auto-numbered.679 /// If this hash map is empty, it means the enum tags are auto-numbered.
435 values: ValueMap,680 values: ValueMap,
436 /// Represents the declarations inside this struct.681 /// Represents the declarations inside this struct.
437 container: Scope.Container,682 namespace: Scope.Namespace,
438 /// Offset from `owner_decl`, points to the enum decl AST node.683 /// Offset from `owner_decl`, points to the enum decl AST node.
439 node_offset: i32,684 node_offset: i32,
440685
...@@ -442,7 +687,54 @@ pub const EnumFull = struct {...@@ -442,7 +687,54 @@ pub const EnumFull = struct {
442687
443 pub fn srcLoc(self: EnumFull) SrcLoc {688 pub fn srcLoc(self: EnumFull) SrcLoc {
444 return .{689 return .{
445 .container = .{ .decl = self.owner_decl },690 .file_scope = self.owner_decl.getFileScope(),
691 .parent_decl_node = self.owner_decl.src_node,
692 .lazy = .{ .node_offset = self.node_offset },
693 };
694 }
695};
696
697pub const Union = struct {
698 /// The Decl that corresponds to the union itself.
699 owner_decl: *Decl,
700 /// An enum type which is used for the tag of the union.
701 /// This type is created even for untagged unions, even when the memory
702 /// layout does not store the tag.
703 /// Whether zig chooses this type or the user specifies it, it is stored here.
704 /// This will be set to the null type until status is `have_field_types`.
705 tag_ty: Type,
706 /// Set of field names in declaration order.
707 fields: std.StringArrayHashMapUnmanaged(Field),
708 /// Represents the declarations inside this union.
709 namespace: Scope.Namespace,
710 /// Offset from `owner_decl`, points to the union decl AST node.
711 node_offset: i32,
712 /// Index of the union_decl ZIR instruction.
713 zir_index: Zir.Inst.Index,
714
715 layout: std.builtin.TypeInfo.ContainerLayout,
716 status: enum {
717 none,
718 field_types_wip,
719 have_field_types,
720 layout_wip,
721 have_layout,
722 },
723
724 pub const Field = struct {
725 /// undefined until `status` is `have_field_types` or `have_layout`.
726 ty: Type,
727 abi_align: Value,
728 };
729
730 pub fn getFullyQualifiedName(s: *Union, gpa: *Allocator) ![]u8 {
731 return s.owner_decl.getFullyQualifiedName(gpa);
732 }
733
734 pub fn srcLoc(self: Union) SrcLoc {
735 return .{
736 .file_scope = self.owner_decl.getFileScope(),
737 .parent_decl_node = self.owner_decl.src_node,
446 .lazy = .{ .node_offset = self.node_offset },738 .lazy = .{ .node_offset = self.node_offset },
447 };739 };
448 }740 }
...@@ -452,19 +744,23 @@ pub const EnumFull = struct {...@@ -452,19 +744,23 @@ pub const EnumFull = struct {
452/// Extern functions do not have this data structure; they are represented by744/// Extern functions do not have this data structure; they are represented by
453/// the `Decl` only, with a `Value` tag of `extern_fn`.745/// the `Decl` only, with a `Value` tag of `extern_fn`.
454pub const Fn = struct {746pub const Fn = struct {
747 /// The Decl that corresponds to the function itself.
455 owner_decl: *Decl,748 owner_decl: *Decl,
456 /// Contains un-analyzed ZIR instructions generated from Zig source AST.
457 /// Even after we finish analysis, the ZIR is kept in memory, so that
458 /// comptime and inline function calls can happen.
459 /// Parameter names are stored here so that they may be referenced for debug info,
460 /// without having source code bytes loaded into memory.
461 /// The number of parameters is determined by referring to the type.
462 /// The first N elements of `extra` are indexes into `string_bytes` to
463 /// a null-terminated string.
464 /// This memory is managed with gpa, must be freed when the function is freed.
465 zir: zir.Code,
466 /// undefined unless analysis state is `success`.749 /// undefined unless analysis state is `success`.
467 body: ir.Body,750 body: ir.Body,
751 /// The ZIR instruction that is a function instruction. Use this to find
752 /// the body. We store this rather than the body directly so that when ZIR
753 /// is regenerated on update(), we can map this to the new corresponding
754 /// ZIR instruction.
755 zir_body_inst: Zir.Inst.Index,
756
757 /// Relative to owner Decl.
758 lbrace_line: u32,
759 /// Relative to owner Decl.
760 rbrace_line: u32,
761 lbrace_column: u16,
762 rbrace_column: u16,
763
468 state: Analysis,764 state: Analysis,
469765
470 pub const Analysis = enum {766 pub const Analysis = enum {
...@@ -486,9 +782,7 @@ pub const Fn = struct {...@@ -486,9 +782,7 @@ pub const Fn = struct {
486 ir.dumpFn(mod, func);782 ir.dumpFn(mod, func);
487 }783 }
488784
489 pub fn deinit(func: *Fn, gpa: *Allocator) void {785 pub fn deinit(func: *Fn, gpa: *Allocator) void {}
490 func.zir.deinit(gpa);
491 }
492};786};
493787
494pub const Var = struct {788pub const Var = struct {
...@@ -504,8 +798,6 @@ pub const Var = struct {...@@ -504,8 +798,6 @@ pub const Var = struct {
504pub const Scope = struct {798pub const Scope = struct {
505 tag: Tag,799 tag: Tag,
506800
507 pub const NameHash = [16]u8;
508
509 pub fn cast(base: *Scope, comptime T: type) ?*T {801 pub fn cast(base: *Scope, comptime T: type) ?*T {
510 if (base.tag != T.base_tag)802 if (base.tag != T.base_tag)
511 return null;803 return null;
...@@ -513,120 +805,38 @@ pub const Scope = struct {...@@ -513,120 +805,38 @@ pub const Scope = struct {
513 return @fieldParentPtr(T, "base", base);805 return @fieldParentPtr(T, "base", base);
514 }806 }
515807
516 /// Returns the arena Allocator associated with the Decl of the Scope.
517 pub fn arena(scope: *Scope) *Allocator {
518 switch (scope.tag) {
519 .block => return scope.cast(Block).?.sema.arena,
520 .gen_zir => return scope.cast(GenZir).?.astgen.arena,
521 .local_val => return scope.cast(LocalVal).?.gen_zir.astgen.arena,
522 .local_ptr => return scope.cast(LocalPtr).?.gen_zir.astgen.arena,
523 .file => unreachable,
524 .container => unreachable,
525 .decl_ref => unreachable,
526 }
527 }
528
529 pub fn ownerDecl(scope: *Scope) ?*Decl {808 pub fn ownerDecl(scope: *Scope) ?*Decl {
530 return switch (scope.tag) {809 return switch (scope.tag) {
531 .block => scope.cast(Block).?.sema.owner_decl,810 .block => scope.cast(Block).?.sema.owner_decl,
532 .gen_zir => scope.cast(GenZir).?.astgen.decl,
533 .local_val => scope.cast(LocalVal).?.gen_zir.astgen.decl,
534 .local_ptr => scope.cast(LocalPtr).?.gen_zir.astgen.decl,
535 .file => null,811 .file => null,
536 .container => null,812 .namespace => null,
537 .decl_ref => scope.cast(DeclRef).?.decl,
538 };813 };
539 }814 }
540815
541 pub fn srcDecl(scope: *Scope) ?*Decl {816 pub fn srcDecl(scope: *Scope) ?*Decl {
542 return switch (scope.tag) {817 return switch (scope.tag) {
543 .block => scope.cast(Block).?.src_decl,818 .block => scope.cast(Block).?.src_decl,
544 .gen_zir => scope.cast(GenZir).?.astgen.decl,
545 .local_val => scope.cast(LocalVal).?.gen_zir.astgen.decl,
546 .local_ptr => scope.cast(LocalPtr).?.gen_zir.astgen.decl,
547 .file => null,819 .file => null,
548 .container => null,820 .namespace => scope.cast(Namespace).?.getDecl(),
549 .decl_ref => scope.cast(DeclRef).?.decl,
550 };821 };
551 }822 }
552823
553 /// Asserts the scope has a parent which is a Container and returns it.824 /// Asserts the scope has a parent which is a Namespace and returns it.
554 pub fn namespace(scope: *Scope) *Container {825 pub fn namespace(scope: *Scope) *Namespace {
555 switch (scope.tag) {826 switch (scope.tag) {
556 .block => return scope.cast(Block).?.sema.owner_decl.container,827 .block => return scope.cast(Block).?.sema.owner_decl.namespace,
557 .gen_zir => return scope.cast(GenZir).?.astgen.decl.container,828 .file => return scope.cast(File).?.root_decl.?.namespace,
558 .local_val => return scope.cast(LocalVal).?.gen_zir.astgen.decl.container,829 .namespace => return scope.cast(Namespace).?,
559 .local_ptr => return scope.cast(LocalPtr).?.gen_zir.astgen.decl.container,
560 .file => return &scope.cast(File).?.root_container,
561 .container => return scope.cast(Container).?,
562 .decl_ref => return scope.cast(DeclRef).?.decl.container,
563 }830 }
564 }831 }
565832
566 /// Must generate unique bytes with no collisions with other decls.833 /// Asserts the scope has a parent which is a Namespace or File and
567 /// The point of hashing here is only to limit the number of bytes of
568 /// the unique identifier to a fixed size (16 bytes).
569 pub fn fullyQualifiedNameHash(scope: *Scope, name: []const u8) NameHash {
570 switch (scope.tag) {
571 .block => unreachable,
572 .gen_zir => unreachable,
573 .local_val => unreachable,
574 .local_ptr => unreachable,
575 .file => unreachable,
576 .container => return scope.cast(Container).?.fullyQualifiedNameHash(name),
577 .decl_ref => unreachable,
578 }
579 }
580
581 /// Asserts the scope is a child of a File and has an AST tree and returns the tree.
582 pub fn tree(scope: *Scope) *const ast.Tree {
583 switch (scope.tag) {
584 .file => return &scope.cast(File).?.tree,
585 .block => return &scope.cast(Block).?.src_decl.container.file_scope.tree,
586 .gen_zir => return scope.cast(GenZir).?.tree(),
587 .local_val => return &scope.cast(LocalVal).?.gen_zir.astgen.decl.container.file_scope.tree,
588 .local_ptr => return &scope.cast(LocalPtr).?.gen_zir.astgen.decl.container.file_scope.tree,
589 .container => return &scope.cast(Container).?.file_scope.tree,
590 .decl_ref => return &scope.cast(DeclRef).?.decl.container.file_scope.tree,
591 }
592 }
593
594 /// Asserts the scope is a child of a `GenZir` and returns it.
595 pub fn getGenZir(scope: *Scope) *GenZir {
596 return switch (scope.tag) {
597 .block => unreachable,
598 .gen_zir => scope.cast(GenZir).?,
599 .local_val => return scope.cast(LocalVal).?.gen_zir,
600 .local_ptr => return scope.cast(LocalPtr).?.gen_zir,
601 .file => unreachable,
602 .container => unreachable,
603 .decl_ref => unreachable,
604 };
605 }
606
607 /// Asserts the scope has a parent which is a Container or File and
608 /// returns the sub_file_path field.834 /// returns the sub_file_path field.
609 pub fn subFilePath(base: *Scope) []const u8 {835 pub fn subFilePath(base: *Scope) []const u8 {
610 switch (base.tag) {836 switch (base.tag) {
611 .container => return @fieldParentPtr(Container, "base", base).file_scope.sub_file_path,837 .namespace => return @fieldParentPtr(Namespace, "base", base).file_scope.sub_file_path,
612 .file => return @fieldParentPtr(File, "base", base).sub_file_path,838 .file => return @fieldParentPtr(File, "base", base).sub_file_path,
613 .block => unreachable,839 .block => unreachable,
614 .gen_zir => unreachable,
615 .local_val => unreachable,
616 .local_ptr => unreachable,
617 .decl_ref => unreachable,
618 }
619 }
620
621 pub fn getSource(base: *Scope, module: *Module) ![:0]const u8 {
622 switch (base.tag) {
623 .container => return @fieldParentPtr(Container, "base", base).file_scope.getSource(module),
624 .file => return @fieldParentPtr(File, "base", base).getSource(module),
625 .gen_zir => unreachable,
626 .local_val => unreachable,
627 .local_ptr => unreachable,
628 .block => unreachable,
629 .decl_ref => unreachable,
630 }840 }
631 }841 }
632842
...@@ -635,70 +845,120 @@ pub const Scope = struct {...@@ -635,70 +845,120 @@ pub const Scope = struct {
635 var cur = base;845 var cur = base;
636 while (true) {846 while (true) {
637 cur = switch (cur.tag) {847 cur = switch (cur.tag) {
638 .container => return @fieldParentPtr(Container, "base", cur).file_scope,848 .namespace => return @fieldParentPtr(Namespace, "base", cur).file_scope,
639 .file => return @fieldParentPtr(File, "base", cur),849 .file => return @fieldParentPtr(File, "base", cur),
640 .gen_zir => @fieldParentPtr(GenZir, "base", cur).parent,850 .block => return @fieldParentPtr(Block, "base", cur).src_decl.namespace.file_scope,
641 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,
642 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,
643 .block => return @fieldParentPtr(Block, "base", cur).src_decl.container.file_scope,
644 .decl_ref => return @fieldParentPtr(DeclRef, "base", cur).decl.container.file_scope,
645 };851 };
646 }852 }
647 }853 }
648854
649 fn name_hash_hash(x: NameHash) u32 {
650 return @truncate(u32, @bitCast(u128, x));
651 }
652
653 fn name_hash_eql(a: NameHash, b: NameHash) bool {
654 return @bitCast(u128, a) == @bitCast(u128, b);
655 }
656
657 pub const Tag = enum {855 pub const Tag = enum {
658 /// .zig source code.856 /// .zig source code.
659 file,857 file,
660 /// struct, enum or union, every .file contains one of these.858 /// Namespace owned by structs, enums, unions, and opaques for decls.
661 container,859 namespace,
662 block,860 block,
663 gen_zir,
664 local_val,
665 local_ptr,
666 /// Used for simple error reporting. Only contains a reference to a
667 /// `Decl` for use with `srcDecl` and `ownerDecl`.
668 /// Has no parents or children.
669 decl_ref,
670 };861 };
671862
672 pub const Container = struct {863 /// The container that structs, enums, unions, and opaques have.
673 pub const base_tag: Tag = .container;864 pub const Namespace = struct {
865 pub const base_tag: Tag = .namespace;
674 base: Scope = Scope{ .tag = base_tag },866 base: Scope = Scope{ .tag = base_tag },
675867
868 parent: ?*Namespace,
676 file_scope: *Scope.File,869 file_scope: *Scope.File,
677 parent_name_hash: NameHash,870 /// Will be a struct, enum, union, or opaque.
678
679 /// Direct children of the file.
680 decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
681 ty: Type,871 ty: Type,
872 /// Direct children of the namespace. Used during an update to detect
873 /// which decls have been added/removed from source.
874 /// Declaration order is preserved via entry order.
875 /// Key memory is owned by `decl.name`.
876 /// TODO save memory with https://github.com/ziglang/zig/issues/8619.
877 /// Anonymous decls are not stored here; they are kept in `anon_decls` instead.
878 decls: std.StringArrayHashMapUnmanaged(*Decl) = .{},
879
880 anon_decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
881
882 pub fn deinit(ns: *Namespace, mod: *Module) void {
883 ns.destroyDecls(mod);
884 ns.* = undefined;
885 }
886
887 pub fn destroyDecls(ns: *Namespace, mod: *Module) void {
888 const gpa = mod.gpa;
889
890 log.debug("destroyDecls {*}", .{ns});
891
892 var decls = ns.decls;
893 ns.decls = .{};
682894
683 pub fn deinit(cont: *Container, gpa: *Allocator) void {895 var anon_decls = ns.anon_decls;
684 cont.decls.deinit(gpa);896 ns.anon_decls = .{};
685 // TODO either Container of File should have an arena for sub_file_path and ty897
686 gpa.destroy(cont.ty.castTag(.empty_struct).?);898 for (decls.items()) |entry| {
687 gpa.free(cont.file_scope.sub_file_path);899 entry.value.destroy(mod);
688 cont.* = undefined;900 }
901 decls.deinit(gpa);
902
903 for (anon_decls.items()) |entry| {
904 entry.key.destroy(mod);
905 }
906 anon_decls.deinit(gpa);
689 }907 }
690908
691 pub fn removeDecl(cont: *Container, child: *Decl) void {909 pub fn deleteAllDecls(
692 _ = cont.decls.swapRemove(child);910 ns: *Namespace,
911 mod: *Module,
912 outdated_decls: ?*std.AutoArrayHashMap(*Decl, void),
913 ) !void {
914 const gpa = mod.gpa;
915
916 log.debug("deleteAllDecls {*}", .{ns});
917
918 var decls = ns.decls;
919 ns.decls = .{};
920
921 var anon_decls = ns.anon_decls;
922 ns.anon_decls = .{};
923
924 // TODO rework this code to not panic on OOM.
925 // (might want to coordinate with the clearDecl function)
926
927 for (decls.items()) |entry| {
928 const child_decl = entry.value;
929 mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory");
930 child_decl.destroy(mod);
931 }
932 decls.deinit(gpa);
933
934 for (anon_decls.items()) |entry| {
935 const child_decl = entry.key;
936 mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory");
937 child_decl.destroy(mod);
938 }
939 anon_decls.deinit(gpa);
693 }940 }
694941
695 pub fn fullyQualifiedNameHash(cont: *Container, name: []const u8) NameHash {942 // This renders e.g. "std.fs.Dir.OpenOptions"
696 return std.zig.hashName(cont.parent_name_hash, ".", name);943 pub fn renderFullyQualifiedName(
944 ns: Namespace,
945 name: []const u8,
946 writer: anytype,
947 ) @TypeOf(writer).Error!void {
948 if (ns.parent) |parent| {
949 const decl = ns.getDecl();
950 try parent.renderFullyQualifiedName(mem.spanZ(decl.name), writer);
951 } else {
952 try ns.file_scope.renderFullyQualifiedName(writer);
953 }
954 if (name.len != 0) {
955 try writer.writeAll(".");
956 try writer.writeAll(name);
957 }
697 }958 }
698959
699 pub fn renderFullyQualifiedName(cont: Container, name: []const u8, writer: anytype) !void {960 pub fn getDecl(ns: Namespace) *Decl {
700 // TODO this should render e.g. "std.fs.Dir.OpenOptions"961 return ns.ty.getOwnerDecl();
701 return writer.writeAll(name);
702 }962 }
703 };963 };
704964
...@@ -707,85 +967,172 @@ pub const Scope = struct {...@@ -707,85 +967,172 @@ pub const Scope = struct {
707 base: Scope = Scope{ .tag = base_tag },967 base: Scope = Scope{ .tag = base_tag },
708 status: enum {968 status: enum {
709 never_loaded,969 never_loaded,
710 unloaded_success,970 retryable_failure,
711 unloaded_parse_failure,971 parse_failure,
712 loaded_success,972 astgen_failure,
973 success_zir,
713 },974 },
714975 source_loaded: bool,
976 tree_loaded: bool,
977 zir_loaded: bool,
715 /// Relative to the owning package's root_src_dir.978 /// Relative to the owning package's root_src_dir.
716 /// Reference to external memory, not owned by File.979 /// Memory is stored in gpa, owned by File.
717 sub_file_path: []const u8,980 sub_file_path: []const u8,
718 source: union(enum) {981 /// Whether this is populated depends on `source_loaded`.
719 unloaded: void,982 source: [:0]const u8,
720 bytes: [:0]const u8,983 /// Whether this is populated depends on `status`.
721 },984 stat_size: u64,
722 /// Whether this is populated or not depends on `status`.985 /// Whether this is populated depends on `status`.
986 stat_inode: std.fs.File.INode,
987 /// Whether this is populated depends on `status`.
988 stat_mtime: i128,
989 /// Whether this is populated or not depends on `tree_loaded`.
723 tree: ast.Tree,990 tree: ast.Tree,
991 /// Whether this is populated or not depends on `zir_loaded`.
992 zir: Zir,
724 /// Package that this file is a part of, managed externally.993 /// Package that this file is a part of, managed externally.
725 pkg: *Package,994 pkg: *Package,
726995 /// The Decl of the struct that represents this File.
727 root_container: Container,996 root_decl: ?*Decl,
997
998 /// Used by change detection algorithm, after astgen, contains the
999 /// set of decls that existed in the previous ZIR but not in the new one.
1000 deleted_decls: std.ArrayListUnmanaged(*Decl) = .{},
1001 /// Used by change detection algorithm, after astgen, contains the
1002 /// set of decls that existed both in the previous ZIR and in the new one,
1003 /// but their source code has been modified.
1004 outdated_decls: std.ArrayListUnmanaged(*Decl) = .{},
1005
1006 /// The most recent successful ZIR for this file, with no errors.
1007 /// This is only populated when a previously successful ZIR
1008 /// newly introduces compile errors during an update. When ZIR is
1009 /// successful, this field is unloaded.
1010 prev_zir: ?*Zir = null,
7281011
729 pub fn unload(file: *File, gpa: *Allocator) void {1012 pub fn unload(file: *File, gpa: *Allocator) void {
730 switch (file.status) {1013 file.unloadTree(gpa);
731 .unloaded_parse_failure,1014 file.unloadSource(gpa);
732 .never_loaded,1015 file.unloadZir(gpa);
733 .unloaded_success,1016 }
734 => {
735 file.status = .unloaded_success;
736 },
7371017
738 .loaded_success => {1018 pub fn unloadTree(file: *File, gpa: *Allocator) void {
739 file.tree.deinit(gpa);1019 if (file.tree_loaded) {
740 file.status = .unloaded_success;1020 file.tree_loaded = false;
741 },1021 file.tree.deinit(gpa);
742 }1022 }
743 switch (file.source) {1023 }
744 .bytes => |bytes| {1024
745 gpa.free(bytes);1025 pub fn unloadSource(file: *File, gpa: *Allocator) void {
746 file.source = .{ .unloaded = {} };1026 if (file.source_loaded) {
747 },1027 file.source_loaded = false;
748 .unloaded => {},1028 gpa.free(file.source);
749 }1029 }
750 }1030 }
7511031
752 pub fn deinit(file: *File, gpa: *Allocator) void {1032 pub fn unloadZir(file: *File, gpa: *Allocator) void {
753 file.root_container.deinit(gpa);1033 if (file.zir_loaded) {
1034 file.zir_loaded = false;
1035 file.zir.deinit(gpa);
1036 }
1037 }
1038
1039 pub fn deinit(file: *File, mod: *Module) void {
1040 const gpa = mod.gpa;
1041 log.debug("deinit File {s}", .{file.sub_file_path});
1042 file.deleted_decls.deinit(gpa);
1043 file.outdated_decls.deinit(gpa);
1044 if (file.root_decl) |root_decl| {
1045 root_decl.destroy(mod);
1046 }
1047 gpa.free(file.sub_file_path);
754 file.unload(gpa);1048 file.unload(gpa);
1049 if (file.prev_zir) |prev_zir| {
1050 prev_zir.deinit(gpa);
1051 gpa.destroy(prev_zir);
1052 }
755 file.* = undefined;1053 file.* = undefined;
756 }1054 }
7571055
758 pub fn destroy(file: *File, gpa: *Allocator) void {1056 pub fn getSource(file: *File, gpa: *Allocator) ![:0]const u8 {
759 file.deinit(gpa);1057 if (file.source_loaded) return file.source;
1058
1059 const root_dir_path = file.pkg.root_src_directory.path orelse ".";
1060 log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{
1061 root_dir_path, file.sub_file_path,
1062 });
1063
1064 // Keep track of inode, file size, mtime, hash so we can detect which files
1065 // have been modified when an incremental update is requested.
1066 var f = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{});
1067 defer f.close();
1068
1069 const stat = try f.stat();
1070
1071 if (stat.size > std.math.maxInt(u32))
1072 return error.FileTooBig;
1073
1074 const source = try gpa.allocSentinel(u8, stat.size, 0);
1075 defer if (!file.source_loaded) gpa.free(source);
1076 const amt = try f.readAll(source);
1077 if (amt != stat.size)
1078 return error.UnexpectedEndOfFile;
1079
1080 // Here we do not modify stat fields because this function is the one
1081 // used for error reporting. We need to keep the stat fields stale so that
1082 // astGenFile can know to regenerate ZIR.
1083
1084 file.source = source;
1085 file.source_loaded = true;
1086 return source;
1087 }
1088
1089 pub fn getTree(file: *File, gpa: *Allocator) !*const ast.Tree {
1090 if (file.tree_loaded) return &file.tree;
1091
1092 const source = try file.getSource(gpa);
1093 file.tree = try std.zig.parse(gpa, source);
1094 file.tree_loaded = true;
1095 return &file.tree;
1096 }
1097
1098 pub fn destroy(file: *File, mod: *Module) void {
1099 const gpa = mod.gpa;
1100 file.deinit(mod);
760 gpa.destroy(file);1101 gpa.destroy(file);
761 }1102 }
7621103
1104 pub fn renderFullyQualifiedName(file: File, writer: anytype) !void {
1105 // Convert all the slashes into dots and truncate the extension.
1106 const ext = std.fs.path.extension(file.sub_file_path);
1107 const noext = file.sub_file_path[0 .. file.sub_file_path.len - ext.len];
1108 for (noext) |byte| switch (byte) {
1109 '/', '\\' => try writer.writeByte('.'),
1110 else => try writer.writeByte(byte),
1111 };
1112 }
1113
1114 pub fn fullyQualifiedNameZ(file: File, gpa: *Allocator) ![:0]u8 {
1115 var buf = std.ArrayList(u8).init(gpa);
1116 defer buf.deinit();
1117 try file.renderFullyQualifiedName(buf.writer());
1118 return buf.toOwnedSliceSentinel(0);
1119 }
1120
763 pub fn dumpSrc(file: *File, src: LazySrcLoc) void {1121 pub fn dumpSrc(file: *File, src: LazySrcLoc) void {
764 const loc = std.zig.findLineColumn(file.source.bytes, src);1122 const loc = std.zig.findLineColumn(file.source.bytes, src);
765 std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 });1123 std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 });
766 }1124 }
7671125
768 pub fn getSource(file: *File, module: *Module) ![:0]const u8 {1126 pub fn okToReportErrors(file: File) bool {
769 switch (file.source) {1127 return switch (file.status) {
770 .unloaded => {1128 .parse_failure, .astgen_failure => false,
771 const source = try file.pkg.root_src_directory.handle.readFileAllocOptions(1129 else => true,
772 module.gpa,1130 };
773 file.sub_file_path,
774 std.math.maxInt(u32),
775 null,
776 1,
777 0,
778 );
779 file.source = .{ .bytes = source };
780 return source;
781 },
782 .bytes => |bytes| return bytes,
783 }
784 }1131 }
785 };1132 };
7861133
787 /// This is the context needed to semantically analyze ZIR instructions and1134 /// This is the context needed to semantically analyze ZIR instructions and
788 /// produce TZIR instructions.1135 /// produce AIR instructions.
789 /// This is a temporary structure stored on the stack; references to it are valid only1136 /// This is a temporary structure stored on the stack; references to it are valid only
790 /// during semantic analysis of the block.1137 /// during semantic analysis of the block.
791 pub const Block = struct {1138 pub const Block = struct {
...@@ -800,20 +1147,20 @@ pub const Scope = struct {...@@ -800,20 +1147,20 @@ pub const Scope = struct {
800 /// for the one that will be the same for all Block instances.1147 /// for the one that will be the same for all Block instances.
801 src_decl: *Decl,1148 src_decl: *Decl,
802 instructions: ArrayListUnmanaged(*ir.Inst),1149 instructions: ArrayListUnmanaged(*ir.Inst),
803 label: ?Label = null,1150 label: ?*Label = null,
804 inlining: ?*Inlining,1151 inlining: ?*Inlining,
805 is_comptime: bool,1152 is_comptime: bool,
8061153
807 /// This `Block` maps a block ZIR instruction to the corresponding1154 /// This `Block` maps a block ZIR instruction to the corresponding
808 /// TZIR instruction for break instruction analysis.1155 /// AIR instruction for break instruction analysis.
809 pub const Label = struct {1156 pub const Label = struct {
810 zir_block: zir.Inst.Index,1157 zir_block: Zir.Inst.Index,
811 merges: Merges,1158 merges: Merges,
812 };1159 };
8131160
814 /// This `Block` indicates that an inline function call is happening1161 /// This `Block` indicates that an inline function call is happening
815 /// and return instructions should be analyzed as a break instruction1162 /// and return instructions should be analyzed as a break instruction
816 /// to this TZIR block instruction.1163 /// to this AIR block instruction.
817 /// It is shared among all the blocks in an inline or comptime called1164 /// It is shared among all the blocks in an inline or comptime called
818 /// function.1165 /// function.
819 pub const Inlining = struct {1166 pub const Inlining = struct {
...@@ -833,7 +1180,7 @@ pub const Scope = struct {...@@ -833,7 +1180,7 @@ pub const Scope = struct {
8331180
834 /// For debugging purposes.1181 /// For debugging purposes.
835 pub fn dump(block: *Block, mod: Module) void {1182 pub fn dump(block: *Block, mod: Module) void {
836 zir.dumpBlock(mod, block);1183 Zir.dumpBlock(mod, block);
837 }1184 }
8381185
839 pub fn makeSubBlock(parent: *Block) Block {1186 pub fn makeSubBlock(parent: *Block) Block {
...@@ -859,7 +1206,7 @@ pub const Scope = struct {...@@ -859,7 +1206,7 @@ pub const Scope = struct {
859 }1206 }
8601207
861 pub fn getFileScope(block: *Block) *Scope.File {1208 pub fn getFileScope(block: *Block) *Scope.File {
862 return block.src_decl.container.file_scope;1209 return block.src_decl.namespace.file_scope;
863 }1210 }
8641211
865 pub fn addNoOp(1212 pub fn addNoOp(
...@@ -1007,7 +1354,7 @@ pub const Scope = struct {...@@ -1007,7 +1354,7 @@ pub const Scope = struct {
1007 return &inst.base;1354 return &inst.base;
1008 }1355 }
10091356
1010 pub fn addDbgStmt(block: *Scope.Block, src: LazySrcLoc, abs_byte_off: u32) !*ir.Inst {1357 pub fn addDbgStmt(block: *Scope.Block, src: LazySrcLoc, line: u32, column: u32) !*ir.Inst {
1011 const inst = try block.sema.arena.create(ir.Inst.DbgStmt);1358 const inst = try block.sema.arena.create(ir.Inst.DbgStmt);
1012 inst.* = .{1359 inst.* = .{
1013 .base = .{1360 .base = .{
...@@ -1015,7 +1362,8 @@ pub const Scope = struct {...@@ -1015,7 +1362,8 @@ pub const Scope = struct {
1015 .ty = Type.initTag(.void),1362 .ty = Type.initTag(.void),
1016 .src = src,1363 .src = src,
1017 },1364 },
1018 .byte_offset = abs_byte_off,1365 .line = line,
1366 .column = column,
1019 };1367 };
1020 try block.instructions.append(block.sema.gpa, &inst.base);1368 try block.instructions.append(block.sema.gpa, &inst.base);
1021 return &inst.base;1369 return &inst.base;
...@@ -1042,695 +1390,127 @@ pub const Scope = struct {...@@ -1042,695 +1390,127 @@ pub const Scope = struct {
1042 return &inst.base;1390 return &inst.base;
1043 }1391 }
1044 };1392 };
1393};
10451394
1046 /// This is a temporary structure; references to it are valid only1395/// This struct holds data necessary to construct API-facing `AllErrors.Message`.
1047 /// while constructing a `zir.Code`.1396/// Its memory is managed with the general purpose allocator so that they
1048 pub const GenZir = struct {1397/// can be created and destroyed in response to incremental updates.
1049 pub const base_tag: Tag = .gen_zir;1398/// In some cases, the Scope.File could have been inferred from where the ErrorMsg
1050 base: Scope = Scope{ .tag = base_tag },1399/// is stored. For example, if it is stored in Module.failed_decls, then the Scope.File
1051 force_comptime: bool,1400/// would be determined by the Decl Scope. However, the data structure contains the field
1052 /// Parents can be: `GenZir`, `File`1401/// anyway so that `ErrorMsg` can be reused for error notes, which may be in a different
1053 parent: *Scope,1402/// file than the parent error message. It also simplifies processing of error messages.
1054 /// All `GenZir` scopes for the same ZIR share this.1403pub const ErrorMsg = struct {
1055 astgen: *AstGen,1404 src_loc: SrcLoc,
1056 /// Keeps track of the list of instructions in this scope only. Indexes1405 msg: []const u8,
1057 /// to instructions in `astgen`.1406 notes: []ErrorMsg = &.{},
1058 instructions: ArrayListUnmanaged(zir.Inst.Index) = .{},
1059 label: ?Label = null,
1060 break_block: zir.Inst.Index = 0,
1061 continue_block: zir.Inst.Index = 0,
1062 /// Only valid when setBreakResultLoc is called.
1063 break_result_loc: AstGen.ResultLoc = undefined,
1064 /// When a block has a pointer result location, here it is.
1065 rl_ptr: zir.Inst.Ref = .none,
1066 /// When a block has a type result location, here it is.
1067 rl_ty_inst: zir.Inst.Ref = .none,
1068 /// Keeps track of how many branches of a block did not actually
1069 /// consume the result location. astgen uses this to figure out
1070 /// whether to rely on break instructions or writing to the result
1071 /// pointer for the result instruction.
1072 rvalue_rl_count: usize = 0,
1073 /// Keeps track of how many break instructions there are. When astgen is finished
1074 /// with a block, it can check this against rvalue_rl_count to find out whether
1075 /// the break instructions should be downgraded to break_void.
1076 break_count: usize = 0,
1077 /// Tracks `break :foo bar` instructions so they can possibly be elided later if
1078 /// the labeled block ends up not needing a result location pointer.
1079 labeled_breaks: ArrayListUnmanaged(zir.Inst.Index) = .{},
1080 /// Tracks `store_to_block_ptr` instructions that correspond to break instructions
1081 /// so they can possibly be elided later if the labeled block ends up not needing
1082 /// a result location pointer.
1083 labeled_store_to_block_ptr_list: ArrayListUnmanaged(zir.Inst.Index) = .{},
10841407
1085 pub const Label = struct {1408 pub fn create(
1086 token: ast.TokenIndex,1409 gpa: *Allocator,
1087 block_inst: zir.Inst.Index,1410 src_loc: SrcLoc,
1088 used: bool = false,1411 comptime format: []const u8,
1089 };1412 args: anytype,
1413 ) !*ErrorMsg {
1414 const err_msg = try gpa.create(ErrorMsg);
1415 errdefer gpa.destroy(err_msg);
1416 err_msg.* = try init(gpa, src_loc, format, args);
1417 return err_msg;
1418 }
10901419
1091 /// Only valid to call on the top of the `GenZir` stack. Completes the1420 /// Assumes the ErrorMsg struct and msg were both allocated with `gpa`,
1092 /// `AstGen` into a `zir.Code`. Leaves the `AstGen` in an1421 /// as well as all notes.
1093 /// initialized, but empty, state.1422 pub fn destroy(err_msg: *ErrorMsg, gpa: *Allocator) void {
1094 pub fn finish(gz: *GenZir) !zir.Code {1423 err_msg.deinit(gpa);
1095 const gpa = gz.astgen.mod.gpa;1424 gpa.destroy(err_msg);
1096 try gz.setBlockBody(0);1425 }
1097 return zir.Code{
1098 .instructions = gz.astgen.instructions.toOwnedSlice(),
1099 .string_bytes = gz.astgen.string_bytes.toOwnedSlice(gpa),
1100 .extra = gz.astgen.extra.toOwnedSlice(gpa),
1101 };
1102 }
11031426
1104 pub fn tokSrcLoc(gz: GenZir, token_index: ast.TokenIndex) LazySrcLoc {1427 pub fn init(
1105 return gz.astgen.decl.tokSrcLoc(token_index);1428 gpa: *Allocator,
1106 }1429 src_loc: SrcLoc,
1430 comptime format: []const u8,
1431 args: anytype,
1432 ) !ErrorMsg {
1433 return ErrorMsg{
1434 .src_loc = src_loc,
1435 .msg = try std.fmt.allocPrint(gpa, format, args),
1436 };
1437 }
11071438
1108 pub fn nodeSrcLoc(gz: GenZir, node_index: ast.Node.Index) LazySrcLoc {1439 pub fn deinit(err_msg: *ErrorMsg, gpa: *Allocator) void {
1109 return gz.astgen.decl.nodeSrcLoc(node_index);1440 for (err_msg.notes) |*note| {
1441 note.deinit(gpa);
1110 }1442 }
1443 gpa.free(err_msg.notes);
1444 gpa.free(err_msg.msg);
1445 err_msg.* = undefined;
1446 }
1447};
11111448
1112 pub fn tree(gz: *const GenZir) *const ast.Tree {1449/// Canonical reference to a position within a source file.
1113 return &gz.astgen.decl.container.file_scope.tree;1450pub const SrcLoc = struct {
1114 }1451 file_scope: *Scope.File,
1452 /// Might be 0 depending on tag of `lazy`.
1453 parent_decl_node: ast.Node.Index,
1454 /// Relative to `parent_decl_node`.
1455 lazy: LazySrcLoc,
11151456
1116 pub fn setBreakResultLoc(gz: *GenZir, parent_rl: AstGen.ResultLoc) void {1457 pub fn declSrcToken(src_loc: SrcLoc) ast.TokenIndex {
1117 // Depending on whether the result location is a pointer or value, different1458 const tree = src_loc.file_scope.tree;
1118 // ZIR needs to be generated. In the former case we rely on storing to the1459 return tree.firstToken(src_loc.parent_decl_node);
1119 // pointer to communicate the result, and use breakvoid; in the latter case1460 }
1120 // the block break instructions will have the result values.
1121 // One more complication: when the result location is a pointer, we detect
1122 // the scenario where the result location is not consumed. In this case
1123 // we emit ZIR for the block break instructions to have the result values,
1124 // and then rvalue() on that to pass the value to the result location.
1125 switch (parent_rl) {
1126 .ty => |ty_inst| {
1127 gz.rl_ty_inst = ty_inst;
1128 gz.break_result_loc = parent_rl;
1129 },
1130 .none_or_ref => {
1131 gz.break_result_loc = .ref;
1132 },
1133 .discard, .none, .ptr, .ref => {
1134 gz.break_result_loc = parent_rl;
1135 },
11361461
1137 .inferred_ptr => |ptr| {1462 pub fn declRelativeToNodeIndex(src_loc: SrcLoc, offset: i32) ast.TokenIndex {
1138 gz.rl_ptr = ptr;1463 return @bitCast(ast.Node.Index, offset + @bitCast(i32, src_loc.parent_decl_node));
1139 gz.break_result_loc = .{ .block_ptr = gz };1464 }
1140 },
11411465
1142 .block_ptr => |parent_block_scope| {1466 pub fn byteOffset(src_loc: SrcLoc, gpa: *Allocator) !u32 {
1143 gz.rl_ty_inst = parent_block_scope.rl_ty_inst;
1144 gz.rl_ptr = parent_block_scope.rl_ptr;
1145 gz.break_result_loc = .{ .block_ptr = gz };
1146 },
1147 }
1148 }
1149
1150 pub fn setBoolBrBody(gz: GenZir, inst: zir.Inst.Index) !void {
1151 const gpa = gz.astgen.mod.gpa;
1152 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
1153 @typeInfo(zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
1154 const zir_datas = gz.astgen.instructions.items(.data);
1155 zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity(
1156 zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
1157 );
1158 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
1159 }
1160
1161 pub fn setBlockBody(gz: GenZir, inst: zir.Inst.Index) !void {
1162 const gpa = gz.astgen.mod.gpa;
1163 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
1164 @typeInfo(zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
1165 const zir_datas = gz.astgen.instructions.items(.data);
1166 zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity(
1167 zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
1168 );
1169 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
1170 }
1171
1172 pub fn identAsString(gz: *GenZir, ident_token: ast.TokenIndex) !u32 {
1173 const astgen = gz.astgen;
1174 const gpa = astgen.mod.gpa;
1175 const string_bytes = &astgen.string_bytes;
1176 const str_index = @intCast(u32, string_bytes.items.len);
1177 try astgen.mod.appendIdentStr(&gz.base, ident_token, string_bytes);
1178 try string_bytes.append(gpa, 0);
1179 return str_index;
1180 }
1181
1182 pub fn addFnTypeCc(gz: *GenZir, tag: zir.Inst.Tag, args: struct {
1183 src_node: ast.Node.Index,
1184 param_types: []const zir.Inst.Ref,
1185 ret_ty: zir.Inst.Ref,
1186 cc: zir.Inst.Ref,
1187 }) !zir.Inst.Ref {
1188 assert(args.src_node != 0);
1189 assert(args.ret_ty != .none);
1190 assert(args.cc != .none);
1191 const gpa = gz.astgen.mod.gpa;
1192 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1193 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1194 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
1195 @typeInfo(zir.Inst.FnTypeCc).Struct.fields.len + args.param_types.len);
1196
1197 const payload_index = gz.astgen.addExtraAssumeCapacity(zir.Inst.FnTypeCc{
1198 .return_type = args.ret_ty,
1199 .cc = args.cc,
1200 .param_types_len = @intCast(u32, args.param_types.len),
1201 });
1202 gz.astgen.appendRefsAssumeCapacity(args.param_types);
1203
1204 const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);
1205 gz.astgen.instructions.appendAssumeCapacity(.{
1206 .tag = tag,
1207 .data = .{ .pl_node = .{
1208 .src_node = gz.astgen.decl.nodeIndexToRelative(args.src_node),
1209 .payload_index = payload_index,
1210 } },
1211 });
1212 gz.instructions.appendAssumeCapacity(new_index);
1213 return gz.astgen.indexToRef(new_index);
1214 }
1215
1216 pub fn addFnType(gz: *GenZir, tag: zir.Inst.Tag, args: struct {
1217 src_node: ast.Node.Index,
1218 ret_ty: zir.Inst.Ref,
1219 param_types: []const zir.Inst.Ref,
1220 }) !zir.Inst.Ref {
1221 assert(args.src_node != 0);
1222 assert(args.ret_ty != .none);
1223 const gpa = gz.astgen.mod.gpa;
1224 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1225 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1226 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
1227 @typeInfo(zir.Inst.FnType).Struct.fields.len + args.param_types.len);
1228
1229 const payload_index = gz.astgen.addExtraAssumeCapacity(zir.Inst.FnType{
1230 .return_type = args.ret_ty,
1231 .param_types_len = @intCast(u32, args.param_types.len),
1232 });
1233 gz.astgen.appendRefsAssumeCapacity(args.param_types);
1234
1235 const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);
1236 gz.astgen.instructions.appendAssumeCapacity(.{
1237 .tag = tag,
1238 .data = .{ .pl_node = .{
1239 .src_node = gz.astgen.decl.nodeIndexToRelative(args.src_node),
1240 .payload_index = payload_index,
1241 } },
1242 });
1243 gz.instructions.appendAssumeCapacity(new_index);
1244 return gz.astgen.indexToRef(new_index);
1245 }
1246
1247 pub fn addCall(
1248 gz: *GenZir,
1249 tag: zir.Inst.Tag,
1250 callee: zir.Inst.Ref,
1251 args: []const zir.Inst.Ref,
1252 /// Absolute node index. This function does the conversion to offset from Decl.
1253 src_node: ast.Node.Index,
1254 ) !zir.Inst.Ref {
1255 assert(callee != .none);
1256 assert(src_node != 0);
1257 const gpa = gz.astgen.mod.gpa;
1258 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1259 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1260 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
1261 @typeInfo(zir.Inst.Call).Struct.fields.len + args.len);
1262
1263 const payload_index = gz.astgen.addExtraAssumeCapacity(zir.Inst.Call{
1264 .callee = callee,
1265 .args_len = @intCast(u32, args.len),
1266 });
1267 gz.astgen.appendRefsAssumeCapacity(args);
1268
1269 const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);
1270 gz.astgen.instructions.appendAssumeCapacity(.{
1271 .tag = tag,
1272 .data = .{ .pl_node = .{
1273 .src_node = gz.astgen.decl.nodeIndexToRelative(src_node),
1274 .payload_index = payload_index,
1275 } },
1276 });
1277 gz.instructions.appendAssumeCapacity(new_index);
1278 return gz.astgen.indexToRef(new_index);
1279 }
1280
1281 /// Note that this returns a `zir.Inst.Index` not a ref.
1282 /// Leaves the `payload_index` field undefined.
1283 pub fn addBoolBr(
1284 gz: *GenZir,
1285 tag: zir.Inst.Tag,
1286 lhs: zir.Inst.Ref,
1287 ) !zir.Inst.Index {
1288 assert(lhs != .none);
1289 const gpa = gz.astgen.mod.gpa;
1290 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1291 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1292
1293 const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);
1294 gz.astgen.instructions.appendAssumeCapacity(.{
1295 .tag = tag,
1296 .data = .{ .bool_br = .{
1297 .lhs = lhs,
1298 .payload_index = undefined,
1299 } },
1300 });
1301 gz.instructions.appendAssumeCapacity(new_index);
1302 return new_index;
1303 }
1304
1305 pub fn addInt(gz: *GenZir, integer: u64) !zir.Inst.Ref {
1306 return gz.add(.{
1307 .tag = .int,
1308 .data = .{ .int = integer },
1309 });
1310 }
1311
1312 pub fn addFloat(gz: *GenZir, number: f32, src_node: ast.Node.Index) !zir.Inst.Ref {
1313 return gz.add(.{
1314 .tag = .float,
1315 .data = .{ .float = .{
1316 .src_node = gz.astgen.decl.nodeIndexToRelative(src_node),
1317 .number = number,
1318 } },
1319 });
1320 }
1321
1322 pub fn addUnNode(
1323 gz: *GenZir,
1324 tag: zir.Inst.Tag,
1325 operand: zir.Inst.Ref,
1326 /// Absolute node index. This function does the conversion to offset from Decl.
1327 src_node: ast.Node.Index,
1328 ) !zir.Inst.Ref {
1329 assert(operand != .none);
1330 return gz.add(.{
1331 .tag = tag,
1332 .data = .{ .un_node = .{
1333 .operand = operand,
1334 .src_node = gz.astgen.decl.nodeIndexToRelative(src_node),
1335 } },
1336 });
1337 }
1338
1339 pub fn addPlNode(
1340 gz: *GenZir,
1341 tag: zir.Inst.Tag,
1342 /// Absolute node index. This function does the conversion to offset from Decl.
1343 src_node: ast.Node.Index,
1344 extra: anytype,
1345 ) !zir.Inst.Ref {
1346 const gpa = gz.astgen.mod.gpa;
1347 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1348 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1349
1350 const payload_index = try gz.astgen.addExtra(extra);
1351 const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);
1352 gz.astgen.instructions.appendAssumeCapacity(.{
1353 .tag = tag,
1354 .data = .{ .pl_node = .{
1355 .src_node = gz.astgen.decl.nodeIndexToRelative(src_node),
1356 .payload_index = payload_index,
1357 } },
1358 });
1359 gz.instructions.appendAssumeCapacity(new_index);
1360 return gz.astgen.indexToRef(new_index);
1361 }
1362
1363 pub fn addArrayTypeSentinel(
1364 gz: *GenZir,
1365 len: zir.Inst.Ref,
1366 sentinel: zir.Inst.Ref,
1367 elem_type: zir.Inst.Ref,
1368 ) !zir.Inst.Ref {
1369 const gpa = gz.astgen.mod.gpa;
1370 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1371 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1372
1373 const payload_index = try gz.astgen.addExtra(zir.Inst.ArrayTypeSentinel{
1374 .sentinel = sentinel,
1375 .elem_type = elem_type,
1376 });
1377 const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);
1378 gz.astgen.instructions.appendAssumeCapacity(.{
1379 .tag = .array_type_sentinel,
1380 .data = .{ .array_type_sentinel = .{
1381 .len = len,
1382 .payload_index = payload_index,
1383 } },
1384 });
1385 gz.instructions.appendAssumeCapacity(new_index);
1386 return gz.astgen.indexToRef(new_index);
1387 }
1388
1389 pub fn addUnTok(
1390 gz: *GenZir,
1391 tag: zir.Inst.Tag,
1392 operand: zir.Inst.Ref,
1393 /// Absolute token index. This function does the conversion to Decl offset.
1394 abs_tok_index: ast.TokenIndex,
1395 ) !zir.Inst.Ref {
1396 assert(operand != .none);
1397 return gz.add(.{
1398 .tag = tag,
1399 .data = .{ .un_tok = .{
1400 .operand = operand,
1401 .src_tok = abs_tok_index - gz.astgen.decl.srcToken(),
1402 } },
1403 });
1404 }
1405
1406 pub fn addStrTok(
1407 gz: *GenZir,
1408 tag: zir.Inst.Tag,
1409 str_index: u32,
1410 /// Absolute token index. This function does the conversion to Decl offset.
1411 abs_tok_index: ast.TokenIndex,
1412 ) !zir.Inst.Ref {
1413 return gz.add(.{
1414 .tag = tag,
1415 .data = .{ .str_tok = .{
1416 .start = str_index,
1417 .src_tok = abs_tok_index - gz.astgen.decl.srcToken(),
1418 } },
1419 });
1420 }
1421
1422 pub fn addBreak(
1423 gz: *GenZir,
1424 tag: zir.Inst.Tag,
1425 break_block: zir.Inst.Index,
1426 operand: zir.Inst.Ref,
1427 ) !zir.Inst.Index {
1428 return gz.addAsIndex(.{
1429 .tag = tag,
1430 .data = .{ .@"break" = .{
1431 .block_inst = break_block,
1432 .operand = operand,
1433 } },
1434 });
1435 }
1436
1437 pub fn addBin(
1438 gz: *GenZir,
1439 tag: zir.Inst.Tag,
1440 lhs: zir.Inst.Ref,
1441 rhs: zir.Inst.Ref,
1442 ) !zir.Inst.Ref {
1443 assert(lhs != .none);
1444 assert(rhs != .none);
1445 return gz.add(.{
1446 .tag = tag,
1447 .data = .{ .bin = .{
1448 .lhs = lhs,
1449 .rhs = rhs,
1450 } },
1451 });
1452 }
1453
1454 pub fn addDecl(
1455 gz: *GenZir,
1456 tag: zir.Inst.Tag,
1457 decl_index: u32,
1458 src_node: ast.Node.Index,
1459 ) !zir.Inst.Ref {
1460 return gz.add(.{
1461 .tag = tag,
1462 .data = .{ .pl_node = .{
1463 .src_node = gz.astgen.decl.nodeIndexToRelative(src_node),
1464 .payload_index = decl_index,
1465 } },
1466 });
1467 }
1468
1469 pub fn addNode(
1470 gz: *GenZir,
1471 tag: zir.Inst.Tag,
1472 /// Absolute node index. This function does the conversion to offset from Decl.
1473 src_node: ast.Node.Index,
1474 ) !zir.Inst.Ref {
1475 return gz.add(.{
1476 .tag = tag,
1477 .data = .{ .node = gz.astgen.decl.nodeIndexToRelative(src_node) },
1478 });
1479 }
1480
1481 /// Asserts that `str` is 8 or fewer bytes.
1482 pub fn addSmallStr(
1483 gz: *GenZir,
1484 tag: zir.Inst.Tag,
1485 str: []const u8,
1486 ) !zir.Inst.Ref {
1487 var buf: [9]u8 = undefined;
1488 mem.copy(u8, &buf, str);
1489 buf[str.len] = 0;
1490
1491 return gz.add(.{
1492 .tag = tag,
1493 .data = .{ .small_str = .{ .bytes = buf[0..8].* } },
1494 });
1495 }
1496
1497 /// Note that this returns a `zir.Inst.Index` not a ref.
1498 /// Does *not* append the block instruction to the scope.
1499 /// Leaves the `payload_index` field undefined.
1500 pub fn addBlock(gz: *GenZir, tag: zir.Inst.Tag, node: ast.Node.Index) !zir.Inst.Index {
1501 const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);
1502 const gpa = gz.astgen.mod.gpa;
1503 try gz.astgen.instructions.append(gpa, .{
1504 .tag = tag,
1505 .data = .{ .pl_node = .{
1506 .src_node = gz.astgen.decl.nodeIndexToRelative(node),
1507 .payload_index = undefined,
1508 } },
1509 });
1510 return new_index;
1511 }
1512
1513 /// Note that this returns a `zir.Inst.Index` not a ref.
1514 /// Leaves the `payload_index` field undefined.
1515 pub fn addCondBr(gz: *GenZir, tag: zir.Inst.Tag, node: ast.Node.Index) !zir.Inst.Index {
1516 const gpa = gz.astgen.mod.gpa;
1517 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1518 const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);
1519 try gz.astgen.instructions.append(gpa, .{
1520 .tag = tag,
1521 .data = .{ .pl_node = .{
1522 .src_node = gz.astgen.decl.nodeIndexToRelative(node),
1523 .payload_index = undefined,
1524 } },
1525 });
1526 gz.instructions.appendAssumeCapacity(new_index);
1527 return new_index;
1528 }
1529
1530 pub fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {
1531 return gz.astgen.indexToRef(try gz.addAsIndex(inst));
1532 }
1533
1534 pub fn addAsIndex(gz: *GenZir, inst: zir.Inst) !zir.Inst.Index {
1535 const gpa = gz.astgen.mod.gpa;
1536 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1537 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1538
1539 const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);
1540 gz.astgen.instructions.appendAssumeCapacity(inst);
1541 gz.instructions.appendAssumeCapacity(new_index);
1542 return new_index;
1543 }
1544 };
1545
1546 /// This is always a `const` local and importantly the `inst` is a value type, not a pointer.
1547 /// This structure lives as long as the AST generation of the Block
1548 /// node that contains the variable.
1549 pub const LocalVal = struct {
1550 pub const base_tag: Tag = .local_val;
1551 base: Scope = Scope{ .tag = base_tag },
1552 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`.
1553 parent: *Scope,
1554 gen_zir: *GenZir,
1555 name: []const u8,
1556 inst: zir.Inst.Ref,
1557 /// Source location of the corresponding variable declaration.
1558 src: LazySrcLoc,
1559 };
1560
1561 /// This could be a `const` or `var` local. It has a pointer instead of a value.
1562 /// This structure lives as long as the AST generation of the Block
1563 /// node that contains the variable.
1564 pub const LocalPtr = struct {
1565 pub const base_tag: Tag = .local_ptr;
1566 base: Scope = Scope{ .tag = base_tag },
1567 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`.
1568 parent: *Scope,
1569 gen_zir: *GenZir,
1570 name: []const u8,
1571 ptr: zir.Inst.Ref,
1572 /// Source location of the corresponding variable declaration.
1573 src: LazySrcLoc,
1574 };
1575
1576 pub const DeclRef = struct {
1577 pub const base_tag: Tag = .decl_ref;
1578 base: Scope = Scope{ .tag = base_tag },
1579 decl: *Decl,
1580 };
1581};
1582
1583/// This struct holds data necessary to construct API-facing `AllErrors.Message`.
1584/// Its memory is managed with the general purpose allocator so that they
1585/// can be created and destroyed in response to incremental updates.
1586/// In some cases, the Scope.File could have been inferred from where the ErrorMsg
1587/// is stored. For example, if it is stored in Module.failed_decls, then the Scope.File
1588/// would be determined by the Decl Scope. However, the data structure contains the field
1589/// anyway so that `ErrorMsg` can be reused for error notes, which may be in a different
1590/// file than the parent error message. It also simplifies processing of error messages.
1591pub const ErrorMsg = struct {
1592 src_loc: SrcLoc,
1593 msg: []const u8,
1594 notes: []ErrorMsg = &.{},
1595
1596 pub fn create(
1597 gpa: *Allocator,
1598 src_loc: SrcLoc,
1599 comptime format: []const u8,
1600 args: anytype,
1601 ) !*ErrorMsg {
1602 const err_msg = try gpa.create(ErrorMsg);
1603 errdefer gpa.destroy(err_msg);
1604 err_msg.* = try init(gpa, src_loc, format, args);
1605 return err_msg;
1606 }
1607
1608 /// Assumes the ErrorMsg struct and msg were both allocated with `gpa`,
1609 /// as well as all notes.
1610 pub fn destroy(err_msg: *ErrorMsg, gpa: *Allocator) void {
1611 err_msg.deinit(gpa);
1612 gpa.destroy(err_msg);
1613 }
1614
1615 pub fn init(
1616 gpa: *Allocator,
1617 src_loc: SrcLoc,
1618 comptime format: []const u8,
1619 args: anytype,
1620 ) !ErrorMsg {
1621 return ErrorMsg{
1622 .src_loc = src_loc,
1623 .msg = try std.fmt.allocPrint(gpa, format, args),
1624 };
1625 }
1626
1627 pub fn deinit(err_msg: *ErrorMsg, gpa: *Allocator) void {
1628 for (err_msg.notes) |*note| {
1629 note.deinit(gpa);
1630 }
1631 gpa.free(err_msg.notes);
1632 gpa.free(err_msg.msg);
1633 err_msg.* = undefined;
1634 }
1635};
1636
1637/// Canonical reference to a position within a source file.
1638pub const SrcLoc = struct {
1639 /// The active field is determined by tag of `lazy`.
1640 container: union {
1641 /// The containing `Decl` according to the source code.
1642 decl: *Decl,
1643 file_scope: *Scope.File,
1644 },
1645 /// Relative to `decl`.
1646 lazy: LazySrcLoc,
1647
1648 pub fn fileScope(src_loc: SrcLoc) *Scope.File {
1649 return switch (src_loc.lazy) {
1650 .unneeded => unreachable,
1651
1652 .byte_abs,
1653 .token_abs,
1654 .node_abs,
1655 => src_loc.container.file_scope,
1656
1657 .byte_offset,
1658 .token_offset,
1659 .node_offset,
1660 .node_offset_back2tok,
1661 .node_offset_var_decl_ty,
1662 .node_offset_for_cond,
1663 .node_offset_builtin_call_arg0,
1664 .node_offset_builtin_call_arg1,
1665 .node_offset_array_access_index,
1666 .node_offset_slice_sentinel,
1667 .node_offset_call_func,
1668 .node_offset_field_name,
1669 .node_offset_deref_ptr,
1670 .node_offset_asm_source,
1671 .node_offset_asm_ret_ty,
1672 .node_offset_if_cond,
1673 .node_offset_bin_op,
1674 .node_offset_bin_lhs,
1675 .node_offset_bin_rhs,
1676 .node_offset_switch_operand,
1677 .node_offset_switch_special_prong,
1678 .node_offset_switch_range,
1679 .node_offset_fn_type_cc,
1680 .node_offset_fn_type_ret_ty,
1681 => src_loc.container.decl.container.file_scope,
1682 };
1683 }
1684
1685 pub fn byteOffset(src_loc: SrcLoc) !u32 {
1686 switch (src_loc.lazy) {1467 switch (src_loc.lazy) {
1687 .unneeded => unreachable,1468 .unneeded => unreachable,
1469 .entire_file => return 0,
16881470
1689 .byte_abs => |byte_index| return byte_index,1471 .byte_abs => |byte_index| return byte_index,
16901472
1691 .token_abs => |tok_index| {1473 .token_abs => |tok_index| {
1692 const tree = src_loc.container.file_scope.base.tree();1474 const tree = try src_loc.file_scope.getTree(gpa);
1693 const token_starts = tree.tokens.items(.start);1475 const token_starts = tree.tokens.items(.start);
1694 return token_starts[tok_index];1476 return token_starts[tok_index];
1695 },1477 },
1696 .node_abs => |node| {1478 .node_abs => |node| {
1697 const tree = src_loc.container.file_scope.base.tree();1479 const tree = try src_loc.file_scope.getTree(gpa);
1698 const token_starts = tree.tokens.items(.start);1480 const token_starts = tree.tokens.items(.start);
1699 const tok_index = tree.firstToken(node);1481 const tok_index = tree.firstToken(node);
1700 return token_starts[tok_index];1482 return token_starts[tok_index];
1701 },1483 },
1702 .byte_offset => |byte_off| {1484 .byte_offset => |byte_off| {
1703 const decl = src_loc.container.decl;1485 const tree = try src_loc.file_scope.getTree(gpa);
1704 return decl.srcByteOffset() + byte_off;1486 const token_starts = tree.tokens.items(.start);
1487 return token_starts[src_loc.declSrcToken()] + byte_off;
1705 },1488 },
1706 .token_offset => |tok_off| {1489 .token_offset => |tok_off| {
1707 const decl = src_loc.container.decl;1490 const tree = try src_loc.file_scope.getTree(gpa);
1708 const tok_index = decl.srcToken() + tok_off;1491 const tok_index = src_loc.declSrcToken() + tok_off;
1709 const tree = decl.container.file_scope.base.tree();
1710 const token_starts = tree.tokens.items(.start);1492 const token_starts = tree.tokens.items(.start);
1711 return token_starts[tok_index];1493 return token_starts[tok_index];
1712 },1494 },
1713 .node_offset, .node_offset_bin_op => |node_off| {1495 .node_offset, .node_offset_bin_op => |node_off| {
1714 const decl = src_loc.container.decl;1496 const tree = try src_loc.file_scope.getTree(gpa);
1715 const node = decl.relativeToNodeIndex(node_off);1497 const node = src_loc.declRelativeToNodeIndex(node_off);
1716 const tree = decl.container.file_scope.base.tree();1498 assert(src_loc.file_scope.tree_loaded);
1717 const main_tokens = tree.nodes.items(.main_token);1499 const main_tokens = tree.nodes.items(.main_token);
1718 const tok_index = main_tokens[node];1500 const tok_index = main_tokens[node];
1719 const token_starts = tree.tokens.items(.start);1501 const token_starts = tree.tokens.items(.start);
1720 return token_starts[tok_index];1502 return token_starts[tok_index];
1721 },1503 },
1722 .node_offset_back2tok => |node_off| {1504 .node_offset_back2tok => |node_off| {
1723 const decl = src_loc.container.decl;1505 const tree = try src_loc.file_scope.getTree(gpa);
1724 const node = decl.relativeToNodeIndex(node_off);1506 const node = src_loc.declRelativeToNodeIndex(node_off);
1725 const tree = decl.container.file_scope.base.tree();
1726 const tok_index = tree.firstToken(node) - 2;1507 const tok_index = tree.firstToken(node) - 2;
1727 const token_starts = tree.tokens.items(.start);1508 const token_starts = tree.tokens.items(.start);
1728 return token_starts[tok_index];1509 return token_starts[tok_index];
1729 },1510 },
1730 .node_offset_var_decl_ty => |node_off| {1511 .node_offset_var_decl_ty => |node_off| {
1731 const decl = src_loc.container.decl;1512 const tree = try src_loc.file_scope.getTree(gpa);
1732 const node = decl.relativeToNodeIndex(node_off);1513 const node = src_loc.declRelativeToNodeIndex(node_off);
1733 const tree = decl.container.file_scope.base.tree();
1734 const node_tags = tree.nodes.items(.tag);1514 const node_tags = tree.nodes.items(.tag);
1735 const full = switch (node_tags[node]) {1515 const full = switch (node_tags[node]) {
1736 .global_var_decl => tree.globalVarDecl(node),1516 .global_var_decl => tree.globalVarDecl(node),
...@@ -1749,11 +1529,10 @@ pub const SrcLoc = struct {...@@ -1749,11 +1529,10 @@ pub const SrcLoc = struct {
1749 return token_starts[tok_index];1529 return token_starts[tok_index];
1750 },1530 },
1751 .node_offset_builtin_call_arg0 => |node_off| {1531 .node_offset_builtin_call_arg0 => |node_off| {
1752 const decl = src_loc.container.decl;1532 const tree = try src_loc.file_scope.getTree(gpa);
1753 const tree = decl.container.file_scope.base.tree();
1754 const node_datas = tree.nodes.items(.data);1533 const node_datas = tree.nodes.items(.data);
1755 const node_tags = tree.nodes.items(.tag);1534 const node_tags = tree.nodes.items(.tag);
1756 const node = decl.relativeToNodeIndex(node_off);1535 const node = src_loc.declRelativeToNodeIndex(node_off);
1757 const param = switch (node_tags[node]) {1536 const param = switch (node_tags[node]) {
1758 .builtin_call_two, .builtin_call_two_comma => node_datas[node].lhs,1537 .builtin_call_two, .builtin_call_two_comma => node_datas[node].lhs,
1759 .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs],1538 .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs],
...@@ -1765,11 +1544,10 @@ pub const SrcLoc = struct {...@@ -1765,11 +1544,10 @@ pub const SrcLoc = struct {
1765 return token_starts[tok_index];1544 return token_starts[tok_index];
1766 },1545 },
1767 .node_offset_builtin_call_arg1 => |node_off| {1546 .node_offset_builtin_call_arg1 => |node_off| {
1768 const decl = src_loc.container.decl;1547 const tree = try src_loc.file_scope.getTree(gpa);
1769 const tree = decl.container.file_scope.base.tree();
1770 const node_datas = tree.nodes.items(.data);1548 const node_datas = tree.nodes.items(.data);
1771 const node_tags = tree.nodes.items(.tag);1549 const node_tags = tree.nodes.items(.tag);
1772 const node = decl.relativeToNodeIndex(node_off);1550 const node = src_loc.declRelativeToNodeIndex(node_off);
1773 const param = switch (node_tags[node]) {1551 const param = switch (node_tags[node]) {
1774 .builtin_call_two, .builtin_call_two_comma => node_datas[node].rhs,1552 .builtin_call_two, .builtin_call_two_comma => node_datas[node].rhs,
1775 .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + 1],1553 .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + 1],
...@@ -1781,22 +1559,20 @@ pub const SrcLoc = struct {...@@ -1781,22 +1559,20 @@ pub const SrcLoc = struct {
1781 return token_starts[tok_index];1559 return token_starts[tok_index];
1782 },1560 },
1783 .node_offset_array_access_index => |node_off| {1561 .node_offset_array_access_index => |node_off| {
1784 const decl = src_loc.container.decl;1562 const tree = try src_loc.file_scope.getTree(gpa);
1785 const tree = decl.container.file_scope.base.tree();
1786 const node_datas = tree.nodes.items(.data);1563 const node_datas = tree.nodes.items(.data);
1787 const node_tags = tree.nodes.items(.tag);1564 const node_tags = tree.nodes.items(.tag);
1788 const node = decl.relativeToNodeIndex(node_off);1565 const node = src_loc.declRelativeToNodeIndex(node_off);
1789 const main_tokens = tree.nodes.items(.main_token);1566 const main_tokens = tree.nodes.items(.main_token);
1790 const tok_index = main_tokens[node_datas[node].rhs];1567 const tok_index = main_tokens[node_datas[node].rhs];
1791 const token_starts = tree.tokens.items(.start);1568 const token_starts = tree.tokens.items(.start);
1792 return token_starts[tok_index];1569 return token_starts[tok_index];
1793 },1570 },
1794 .node_offset_slice_sentinel => |node_off| {1571 .node_offset_slice_sentinel => |node_off| {
1795 const decl = src_loc.container.decl;1572 const tree = try src_loc.file_scope.getTree(gpa);
1796 const tree = decl.container.file_scope.base.tree();
1797 const node_datas = tree.nodes.items(.data);1573 const node_datas = tree.nodes.items(.data);
1798 const node_tags = tree.nodes.items(.tag);1574 const node_tags = tree.nodes.items(.tag);
1799 const node = decl.relativeToNodeIndex(node_off);1575 const node = src_loc.declRelativeToNodeIndex(node_off);
1800 const full = switch (node_tags[node]) {1576 const full = switch (node_tags[node]) {
1801 .slice_open => tree.sliceOpen(node),1577 .slice_open => tree.sliceOpen(node),
1802 .slice => tree.slice(node),1578 .slice => tree.slice(node),
...@@ -1809,11 +1585,10 @@ pub const SrcLoc = struct {...@@ -1809,11 +1585,10 @@ pub const SrcLoc = struct {
1809 return token_starts[tok_index];1585 return token_starts[tok_index];
1810 },1586 },
1811 .node_offset_call_func => |node_off| {1587 .node_offset_call_func => |node_off| {
1812 const decl = src_loc.container.decl;1588 const tree = try src_loc.file_scope.getTree(gpa);
1813 const tree = decl.container.file_scope.base.tree();
1814 const node_datas = tree.nodes.items(.data);1589 const node_datas = tree.nodes.items(.data);
1815 const node_tags = tree.nodes.items(.tag);1590 const node_tags = tree.nodes.items(.tag);
1816 const node = decl.relativeToNodeIndex(node_off);1591 const node = src_loc.declRelativeToNodeIndex(node_off);
1817 var params: [1]ast.Node.Index = undefined;1592 var params: [1]ast.Node.Index = undefined;
1818 const full = switch (node_tags[node]) {1593 const full = switch (node_tags[node]) {
1819 .call_one,1594 .call_one,
...@@ -1836,11 +1611,10 @@ pub const SrcLoc = struct {...@@ -1836,11 +1611,10 @@ pub const SrcLoc = struct {
1836 return token_starts[tok_index];1611 return token_starts[tok_index];
1837 },1612 },
1838 .node_offset_field_name => |node_off| {1613 .node_offset_field_name => |node_off| {
1839 const decl = src_loc.container.decl;1614 const tree = try src_loc.file_scope.getTree(gpa);
1840 const tree = decl.container.file_scope.base.tree();
1841 const node_datas = tree.nodes.items(.data);1615 const node_datas = tree.nodes.items(.data);
1842 const node_tags = tree.nodes.items(.tag);1616 const node_tags = tree.nodes.items(.tag);
1843 const node = decl.relativeToNodeIndex(node_off);1617 const node = src_loc.declRelativeToNodeIndex(node_off);
1844 const tok_index = switch (node_tags[node]) {1618 const tok_index = switch (node_tags[node]) {
1845 .field_access => node_datas[node].rhs,1619 .field_access => node_datas[node].rhs,
1846 else => tree.firstToken(node) - 2,1620 else => tree.firstToken(node) - 2,
...@@ -1849,21 +1623,19 @@ pub const SrcLoc = struct {...@@ -1849,21 +1623,19 @@ pub const SrcLoc = struct {
1849 return token_starts[tok_index];1623 return token_starts[tok_index];
1850 },1624 },
1851 .node_offset_deref_ptr => |node_off| {1625 .node_offset_deref_ptr => |node_off| {
1852 const decl = src_loc.container.decl;1626 const tree = try src_loc.file_scope.getTree(gpa);
1853 const tree = decl.container.file_scope.base.tree();
1854 const node_datas = tree.nodes.items(.data);1627 const node_datas = tree.nodes.items(.data);
1855 const node_tags = tree.nodes.items(.tag);1628 const node_tags = tree.nodes.items(.tag);
1856 const node = decl.relativeToNodeIndex(node_off);1629 const node = src_loc.declRelativeToNodeIndex(node_off);
1857 const tok_index = node_datas[node].lhs;1630 const tok_index = node_datas[node].lhs;
1858 const token_starts = tree.tokens.items(.start);1631 const token_starts = tree.tokens.items(.start);
1859 return token_starts[tok_index];1632 return token_starts[tok_index];
1860 },1633 },
1861 .node_offset_asm_source => |node_off| {1634 .node_offset_asm_source => |node_off| {
1862 const decl = src_loc.container.decl;1635 const tree = try src_loc.file_scope.getTree(gpa);
1863 const tree = decl.container.file_scope.base.tree();
1864 const node_datas = tree.nodes.items(.data);1636 const node_datas = tree.nodes.items(.data);
1865 const node_tags = tree.nodes.items(.tag);1637 const node_tags = tree.nodes.items(.tag);
1866 const node = decl.relativeToNodeIndex(node_off);1638 const node = src_loc.declRelativeToNodeIndex(node_off);
1867 const full = switch (node_tags[node]) {1639 const full = switch (node_tags[node]) {
1868 .asm_simple => tree.asmSimple(node),1640 .asm_simple => tree.asmSimple(node),
1869 .@"asm" => tree.asmFull(node),1641 .@"asm" => tree.asmFull(node),
...@@ -1875,11 +1647,10 @@ pub const SrcLoc = struct {...@@ -1875,11 +1647,10 @@ pub const SrcLoc = struct {
1875 return token_starts[tok_index];1647 return token_starts[tok_index];
1876 },1648 },
1877 .node_offset_asm_ret_ty => |node_off| {1649 .node_offset_asm_ret_ty => |node_off| {
1878 const decl = src_loc.container.decl;1650 const tree = try src_loc.file_scope.getTree(gpa);
1879 const tree = decl.container.file_scope.base.tree();
1880 const node_datas = tree.nodes.items(.data);1651 const node_datas = tree.nodes.items(.data);
1881 const node_tags = tree.nodes.items(.tag);1652 const node_tags = tree.nodes.items(.tag);
1882 const node = decl.relativeToNodeIndex(node_off);1653 const node = src_loc.declRelativeToNodeIndex(node_off);
1883 const full = switch (node_tags[node]) {1654 const full = switch (node_tags[node]) {
1884 .asm_simple => tree.asmSimple(node),1655 .asm_simple => tree.asmSimple(node),
1885 .@"asm" => tree.asmFull(node),1656 .@"asm" => tree.asmFull(node),
...@@ -1892,9 +1663,8 @@ pub const SrcLoc = struct {...@@ -1892,9 +1663,8 @@ pub const SrcLoc = struct {
1892 },1663 },
18931664
1894 .node_offset_for_cond, .node_offset_if_cond => |node_off| {1665 .node_offset_for_cond, .node_offset_if_cond => |node_off| {
1895 const decl = src_loc.container.decl;1666 const tree = try src_loc.file_scope.getTree(gpa);
1896 const node = decl.relativeToNodeIndex(node_off);1667 const node = src_loc.declRelativeToNodeIndex(node_off);
1897 const tree = decl.container.file_scope.base.tree();
1898 const node_tags = tree.nodes.items(.tag);1668 const node_tags = tree.nodes.items(.tag);
1899 const src_node = switch (node_tags[node]) {1669 const src_node = switch (node_tags[node]) {
1900 .if_simple => tree.ifSimple(node).ast.cond_expr,1670 .if_simple => tree.ifSimple(node).ast.cond_expr,
...@@ -1912,9 +1682,8 @@ pub const SrcLoc = struct {...@@ -1912,9 +1682,8 @@ pub const SrcLoc = struct {
1912 return token_starts[tok_index];1682 return token_starts[tok_index];
1913 },1683 },
1914 .node_offset_bin_lhs => |node_off| {1684 .node_offset_bin_lhs => |node_off| {
1915 const decl = src_loc.container.decl;1685 const tree = try src_loc.file_scope.getTree(gpa);
1916 const node = decl.relativeToNodeIndex(node_off);1686 const node = src_loc.declRelativeToNodeIndex(node_off);
1917 const tree = decl.container.file_scope.base.tree();
1918 const node_datas = tree.nodes.items(.data);1687 const node_datas = tree.nodes.items(.data);
1919 const src_node = node_datas[node].lhs;1688 const src_node = node_datas[node].lhs;
1920 const main_tokens = tree.nodes.items(.main_token);1689 const main_tokens = tree.nodes.items(.main_token);
...@@ -1923,9 +1692,8 @@ pub const SrcLoc = struct {...@@ -1923,9 +1692,8 @@ pub const SrcLoc = struct {
1923 return token_starts[tok_index];1692 return token_starts[tok_index];
1924 },1693 },
1925 .node_offset_bin_rhs => |node_off| {1694 .node_offset_bin_rhs => |node_off| {
1926 const decl = src_loc.container.decl;1695 const tree = try src_loc.file_scope.getTree(gpa);
1927 const node = decl.relativeToNodeIndex(node_off);1696 const node = src_loc.declRelativeToNodeIndex(node_off);
1928 const tree = decl.container.file_scope.base.tree();
1929 const node_datas = tree.nodes.items(.data);1697 const node_datas = tree.nodes.items(.data);
1930 const src_node = node_datas[node].rhs;1698 const src_node = node_datas[node].rhs;
1931 const main_tokens = tree.nodes.items(.main_token);1699 const main_tokens = tree.nodes.items(.main_token);
...@@ -1935,9 +1703,8 @@ pub const SrcLoc = struct {...@@ -1935,9 +1703,8 @@ pub const SrcLoc = struct {
1935 },1703 },
19361704
1937 .node_offset_switch_operand => |node_off| {1705 .node_offset_switch_operand => |node_off| {
1938 const decl = src_loc.container.decl;1706 const tree = try src_loc.file_scope.getTree(gpa);
1939 const node = decl.relativeToNodeIndex(node_off);1707 const node = src_loc.declRelativeToNodeIndex(node_off);
1940 const tree = decl.container.file_scope.base.tree();
1941 const node_datas = tree.nodes.items(.data);1708 const node_datas = tree.nodes.items(.data);
1942 const src_node = node_datas[node].lhs;1709 const src_node = node_datas[node].lhs;
1943 const main_tokens = tree.nodes.items(.main_token);1710 const main_tokens = tree.nodes.items(.main_token);
...@@ -1947,9 +1714,8 @@ pub const SrcLoc = struct {...@@ -1947,9 +1714,8 @@ pub const SrcLoc = struct {
1947 },1714 },
19481715
1949 .node_offset_switch_special_prong => |node_off| {1716 .node_offset_switch_special_prong => |node_off| {
1950 const decl = src_loc.container.decl;1717 const tree = try src_loc.file_scope.getTree(gpa);
1951 const switch_node = decl.relativeToNodeIndex(node_off);1718 const switch_node = src_loc.declRelativeToNodeIndex(node_off);
1952 const tree = decl.container.file_scope.base.tree();
1953 const node_datas = tree.nodes.items(.data);1719 const node_datas = tree.nodes.items(.data);
1954 const node_tags = tree.nodes.items(.tag);1720 const node_tags = tree.nodes.items(.tag);
1955 const main_tokens = tree.nodes.items(.main_token);1721 const main_tokens = tree.nodes.items(.main_token);
...@@ -1974,9 +1740,8 @@ pub const SrcLoc = struct {...@@ -1974,9 +1740,8 @@ pub const SrcLoc = struct {
1974 },1740 },
19751741
1976 .node_offset_switch_range => |node_off| {1742 .node_offset_switch_range => |node_off| {
1977 const decl = src_loc.container.decl;1743 const tree = try src_loc.file_scope.getTree(gpa);
1978 const switch_node = decl.relativeToNodeIndex(node_off);1744 const switch_node = src_loc.declRelativeToNodeIndex(node_off);
1979 const tree = decl.container.file_scope.base.tree();
1980 const node_datas = tree.nodes.items(.data);1745 const node_datas = tree.nodes.items(.data);
1981 const node_tags = tree.nodes.items(.tag);1746 const node_tags = tree.nodes.items(.tag);
1982 const main_tokens = tree.nodes.items(.main_token);1747 const main_tokens = tree.nodes.items(.main_token);
...@@ -2005,11 +1770,10 @@ pub const SrcLoc = struct {...@@ -2005,11 +1770,10 @@ pub const SrcLoc = struct {
2005 },1770 },
20061771
2007 .node_offset_fn_type_cc => |node_off| {1772 .node_offset_fn_type_cc => |node_off| {
2008 const decl = src_loc.container.decl;1773 const tree = try src_loc.file_scope.getTree(gpa);
2009 const tree = decl.container.file_scope.base.tree();
2010 const node_datas = tree.nodes.items(.data);1774 const node_datas = tree.nodes.items(.data);
2011 const node_tags = tree.nodes.items(.tag);1775 const node_tags = tree.nodes.items(.tag);
2012 const node = decl.relativeToNodeIndex(node_off);1776 const node = src_loc.declRelativeToNodeIndex(node_off);
2013 var params: [1]ast.Node.Index = undefined;1777 var params: [1]ast.Node.Index = undefined;
2014 const full = switch (node_tags[node]) {1778 const full = switch (node_tags[node]) {
2015 .fn_proto_simple => tree.fnProtoSimple(&params, node),1779 .fn_proto_simple => tree.fnProtoSimple(&params, node),
...@@ -2025,11 +1789,10 @@ pub const SrcLoc = struct {...@@ -2025,11 +1789,10 @@ pub const SrcLoc = struct {
2025 },1789 },
20261790
2027 .node_offset_fn_type_ret_ty => |node_off| {1791 .node_offset_fn_type_ret_ty => |node_off| {
2028 const decl = src_loc.container.decl;1792 const tree = try src_loc.file_scope.getTree(gpa);
2029 const tree = decl.container.file_scope.base.tree();
2030 const node_datas = tree.nodes.items(.data);1793 const node_datas = tree.nodes.items(.data);
2031 const node_tags = tree.nodes.items(.tag);1794 const node_tags = tree.nodes.items(.tag);
2032 const node = decl.relativeToNodeIndex(node_off);1795 const node = src_loc.declRelativeToNodeIndex(node_off);
2033 var params: [1]ast.Node.Index = undefined;1796 var params: [1]ast.Node.Index = undefined;
2034 const full = switch (node_tags[node]) {1797 const full = switch (node_tags[node]) {
2035 .fn_proto_simple => tree.fnProtoSimple(&params, node),1798 .fn_proto_simple => tree.fnProtoSimple(&params, node),
...@@ -2043,6 +1806,46 @@ pub const SrcLoc = struct {...@@ -2043,6 +1806,46 @@ pub const SrcLoc = struct {
2043 const token_starts = tree.tokens.items(.start);1806 const token_starts = tree.tokens.items(.start);
2044 return token_starts[tok_index];1807 return token_starts[tok_index];
2045 },1808 },
1809
1810 .node_offset_anyframe_type => |node_off| {
1811 const tree = try src_loc.file_scope.getTree(gpa);
1812 const node_datas = tree.nodes.items(.data);
1813 const node_tags = tree.nodes.items(.tag);
1814 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
1815 const node = node_datas[parent_node].rhs;
1816 const main_tokens = tree.nodes.items(.main_token);
1817 const tok_index = main_tokens[node];
1818 const token_starts = tree.tokens.items(.start);
1819 return token_starts[tok_index];
1820 },
1821
1822 .node_offset_lib_name => |node_off| {
1823 const tree = try src_loc.file_scope.getTree(gpa);
1824 const node_datas = tree.nodes.items(.data);
1825 const node_tags = tree.nodes.items(.tag);
1826 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
1827 var params: [1]ast.Node.Index = undefined;
1828 const full = switch (node_tags[parent_node]) {
1829 .fn_proto_simple => tree.fnProtoSimple(&params, parent_node),
1830 .fn_proto_multi => tree.fnProtoMulti(parent_node),
1831 .fn_proto_one => tree.fnProtoOne(&params, parent_node),
1832 .fn_proto => tree.fnProto(parent_node),
1833 .fn_decl => blk: {
1834 const fn_proto = node_datas[parent_node].lhs;
1835 break :blk switch (node_tags[fn_proto]) {
1836 .fn_proto_simple => tree.fnProtoSimple(&params, fn_proto),
1837 .fn_proto_multi => tree.fnProtoMulti(fn_proto),
1838 .fn_proto_one => tree.fnProtoOne(&params, fn_proto),
1839 .fn_proto => tree.fnProto(fn_proto),
1840 else => unreachable,
1841 };
1842 },
1843 else => unreachable,
1844 };
1845 const tok_index = full.lib_name.?;
1846 const token_starts = tree.tokens.items(.start);
1847 return token_starts[tok_index];
1848 },
2046 }1849 }
2047 }1850 }
2048};1851};
...@@ -2062,6 +1865,9 @@ pub const LazySrcLoc = union(enum) {...@@ -2062,6 +1865,9 @@ pub const LazySrcLoc = union(enum) {
2062 /// look into using reverse-continue with a memory watchpoint to see where the1865 /// look into using reverse-continue with a memory watchpoint to see where the
2063 /// value is being set to this tag.1866 /// value is being set to this tag.
2064 unneeded,1867 unneeded,
1868 /// Means the source location points to an entire file; not any particular
1869 /// location within the file. `file_scope` union field will be active.
1870 entire_file,
2065 /// The source location points to a byte offset within a source file,1871 /// The source location points to a byte offset within a source file,
2066 /// offset from 0. The source file is determined contextually.1872 /// offset from 0. The source file is determined contextually.
2067 /// Inside a `SrcLoc`, the `file_scope` union field will be active.1873 /// Inside a `SrcLoc`, the `file_scope` union field will be active.
...@@ -2199,16 +2005,30 @@ pub const LazySrcLoc = union(enum) {...@@ -2199,16 +2005,30 @@ pub const LazySrcLoc = union(enum) {
2199 /// the return type node.2005 /// the return type node.
2200 /// The Decl is determined contextually.2006 /// The Decl is determined contextually.
2201 node_offset_fn_type_ret_ty: i32,2007 node_offset_fn_type_ret_ty: i32,
2008 /// The source location points to the type expression of an `anyframe->T`
2009 /// expression, found by taking this AST node index offset from the containing
2010 /// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate
2011 /// to the type expression.
2012 /// The Decl is determined contextually.
2013 node_offset_anyframe_type: i32,
2014 /// The source location points to the string literal of `extern "foo"`, found
2015 /// by taking this AST node index offset from the containing
2016 /// Decl AST node, which points to a function prototype or variable declaration
2017 /// expression AST node. Next, navigate to the string literal of the `extern "foo"`.
2018 /// The Decl is determined contextually.
2019 node_offset_lib_name: i32,
22022020
2203 /// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope.2021 /// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope.
2204 pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc {2022 pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc {
2205 return switch (lazy) {2023 return switch (lazy) {
2206 .unneeded,2024 .unneeded,
2025 .entire_file,
2207 .byte_abs,2026 .byte_abs,
2208 .token_abs,2027 .token_abs,
2209 .node_abs,2028 .node_abs,
2210 => .{2029 => .{
2211 .container = .{ .file_scope = scope.getFileScope() },2030 .file_scope = scope.getFileScope(),
2031 .parent_decl_node = 0,
2212 .lazy = lazy,2032 .lazy = lazy,
2213 },2033 },
22142034
...@@ -2236,8 +2056,11 @@ pub const LazySrcLoc = union(enum) {...@@ -2236,8 +2056,11 @@ pub const LazySrcLoc = union(enum) {
2236 .node_offset_switch_range,2056 .node_offset_switch_range,
2237 .node_offset_fn_type_cc,2057 .node_offset_fn_type_cc,
2238 .node_offset_fn_type_ret_ty,2058 .node_offset_fn_type_ret_ty,
2059 .node_offset_anyframe_type,
2060 .node_offset_lib_name,
2239 => .{2061 => .{
2240 .container = .{ .decl = scope.srcDecl().? },2062 .file_scope = scope.getFileScope(),
2063 .parent_decl_node = scope.srcDecl().?.src_node,
2241 .lazy = lazy,2064 .lazy = lazy,
2242 },2065 },
2243 };2066 };
...@@ -2247,11 +2070,13 @@ pub const LazySrcLoc = union(enum) {...@@ -2247,11 +2070,13 @@ pub const LazySrcLoc = union(enum) {
2247 pub fn toSrcLocWithDecl(lazy: LazySrcLoc, decl: *Decl) SrcLoc {2070 pub fn toSrcLocWithDecl(lazy: LazySrcLoc, decl: *Decl) SrcLoc {
2248 return switch (lazy) {2071 return switch (lazy) {
2249 .unneeded,2072 .unneeded,
2073 .entire_file,
2250 .byte_abs,2074 .byte_abs,
2251 .token_abs,2075 .token_abs,
2252 .node_abs,2076 .node_abs,
2253 => .{2077 => .{
2254 .container = .{ .file_scope = decl.getFileScope() },2078 .file_scope = decl.getFileScope(),
2079 .parent_decl_node = 0,
2255 .lazy = lazy,2080 .lazy = lazy,
2256 },2081 },
22572082
...@@ -2279,8 +2104,11 @@ pub const LazySrcLoc = union(enum) {...@@ -2279,8 +2104,11 @@ pub const LazySrcLoc = union(enum) {
2279 .node_offset_switch_range,2104 .node_offset_switch_range,
2280 .node_offset_fn_type_cc,2105 .node_offset_fn_type_cc,
2281 .node_offset_fn_type_ret_ty,2106 .node_offset_fn_type_ret_ty,
2107 .node_offset_anyframe_type,
2108 .node_offset_lib_name,
2282 => .{2109 => .{
2283 .container = .{ .decl = decl },2110 .file_scope = decl.getFileScope(),
2111 .parent_decl_node = decl.src_node,
2284 .lazy = lazy,2112 .lazy = lazy,
2285 },2113 },
2286 };2114 };
...@@ -2292,6 +2120,14 @@ pub const InnerError = error{ OutOfMemory, AnalysisFail };...@@ -2292,6 +2120,14 @@ pub const InnerError = error{ OutOfMemory, AnalysisFail };
2292pub fn deinit(mod: *Module) void {2120pub fn deinit(mod: *Module) void {
2293 const gpa = mod.gpa;2121 const gpa = mod.gpa;
22942122
2123 for (mod.import_table.items()) |entry| {
2124 gpa.free(entry.key);
2125 entry.value.destroy(mod);
2126 }
2127 mod.import_table.deinit(gpa);
2128
2129 mod.deletion_set.deinit(gpa);
2130
2295 // The callsite of `Compilation.create` owns the `root_pkg`, however2131 // The callsite of `Compilation.create` owns the `root_pkg`, however
2296 // Module owns the builtin and std packages that it adds.2132 // Module owns the builtin and std packages that it adds.
2297 if (mod.root_pkg.table.remove("builtin")) |entry| {2133 if (mod.root_pkg.table.remove("builtin")) |entry| {
...@@ -2309,26 +2145,25 @@ pub fn deinit(mod: *Module) void {...@@ -2309,26 +2145,25 @@ pub fn deinit(mod: *Module) void {
2309 mod.compile_log_text.deinit(gpa);2145 mod.compile_log_text.deinit(gpa);
23102146
2311 mod.zig_cache_artifact_directory.handle.close();2147 mod.zig_cache_artifact_directory.handle.close();
23122148 mod.local_zir_cache.handle.close();
2313 mod.deletion_set.deinit(gpa);2149 mod.global_zir_cache.handle.close();
2314
2315 for (mod.decl_table.items()) |entry| {
2316 entry.value.destroy(mod);
2317 }
2318 mod.decl_table.deinit(gpa);
23192150
2320 for (mod.failed_decls.items()) |entry| {2151 for (mod.failed_decls.items()) |entry| {
2321 entry.value.destroy(gpa);2152 entry.value.destroy(gpa);
2322 }2153 }
2323 mod.failed_decls.deinit(gpa);2154 mod.failed_decls.deinit(gpa);
23242155
2325 for (mod.emit_h_failed_decls.items()) |entry| {2156 if (mod.emit_h) |emit_h| {
2326 entry.value.destroy(gpa);2157 for (emit_h.failed_decls.items()) |entry| {
2158 entry.value.destroy(gpa);
2159 }
2160 emit_h.failed_decls.deinit(gpa);
2161 emit_h.decl_table.deinit(gpa);
2162 gpa.destroy(emit_h);
2327 }2163 }
2328 mod.emit_h_failed_decls.deinit(gpa);
23292164
2330 for (mod.failed_files.items()) |entry| {2165 for (mod.failed_files.items()) |entry| {
2331 entry.value.destroy(gpa);2166 if (entry.value) |msg| msg.destroy(gpa);
2332 }2167 }
2333 mod.failed_files.deinit(gpa);2168 mod.failed_files.deinit(gpa);
23342169
...@@ -2350,9 +2185,6 @@ pub fn deinit(mod: *Module) void {...@@ -2350,9 +2185,6 @@ pub fn deinit(mod: *Module) void {
2350 }2185 }
2351 mod.export_owners.deinit(gpa);2186 mod.export_owners.deinit(gpa);
23522187
2353 mod.symbol_exports.deinit(gpa);
2354 mod.root_scope.destroy(gpa);
2355
2356 var it = mod.global_error_set.iterator();2188 var it = mod.global_error_set.iterator();
2357 while (it.next()) |entry| {2189 while (it.next()) |entry| {
2358 gpa.free(entry.key);2190 gpa.free(entry.key);
...@@ -2360,11 +2192,6 @@ pub fn deinit(mod: *Module) void {...@@ -2360,11 +2192,6 @@ pub fn deinit(mod: *Module) void {
2360 mod.global_error_set.deinit(gpa);2192 mod.global_error_set.deinit(gpa);
23612193
2362 mod.error_name_list.deinit(gpa);2194 mod.error_name_list.deinit(gpa);
2363
2364 for (mod.import_table.items()) |entry| {
2365 entry.value.destroy(gpa);
2366 }
2367 mod.import_table.deinit(gpa);
2368}2195}
23692196
2370fn freeExportList(gpa: *Allocator, export_list: []*Export) void {2197fn freeExportList(gpa: *Allocator, export_list: []*Export) void {
...@@ -2375,1260 +2202,1242 @@ fn freeExportList(gpa: *Allocator, export_list: []*Export) void {...@@ -2375,1260 +2202,1242 @@ fn freeExportList(gpa: *Allocator, export_list: []*Export) void {
2375 gpa.free(export_list);2202 gpa.free(export_list);
2376}2203}
23772204
2378pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) InnerError!void {2205const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8;
2206// TODO This is taking advantage of matching stage1 debug union layout.
2207// We need a better language feature for initializing a union with
2208// a runtime known tag.
2209const Stage1DataLayout = extern struct {
2210 data: [8]u8 align(8),
2211 safety_tag: u8,
2212};
2213comptime {
2214 if (data_has_safety_tag) {
2215 assert(@sizeOf(Stage1DataLayout) == @sizeOf(Zir.Inst.Data));
2216 }
2217}
2218
2219pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node) !void {
2379 const tracy = trace(@src());2220 const tracy = trace(@src());
2380 defer tracy.end();2221 defer tracy.end();
23812222
2382 const subsequent_analysis = switch (decl.analysis) {2223 const comp = mod.comp;
2383 .in_progress => unreachable,2224 const gpa = mod.gpa;
23842225
2385 .sema_failure,2226 // In any case we need to examine the stat of the file to determine the course of action.
2386 .sema_failure_retryable,2227 var source_file = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{});
2387 .codegen_failure,2228 defer source_file.close();
2388 .dependency_failure,
2389 .codegen_failure_retryable,
2390 => return error.AnalysisFail,
23912229
2392 .complete => return,2230 const stat = try source_file.stat();
23932231
2394 .outdated => blk: {2232 const want_local_cache = file.pkg == mod.root_pkg;
2395 log.debug("re-analyzing {s}", .{decl.name});2233 const digest = hash: {
2234 var path_hash: Cache.HashHelper = .{};
2235 if (!want_local_cache) {
2236 path_hash.addOptionalBytes(file.pkg.root_src_directory.path);
2237 }
2238 path_hash.addBytes(file.sub_file_path);
2239 break :hash path_hash.final();
2240 };
2241 const cache_directory = if (want_local_cache) mod.local_zir_cache else mod.global_zir_cache;
2242 const zir_dir = cache_directory.handle;
2243
2244 var cache_file: ?std.fs.File = null;
2245 defer if (cache_file) |f| f.close();
2246
2247 // Determine whether we need to reload the file from disk and redo parsing and AstGen.
2248 switch (file.status) {
2249 .never_loaded, .retryable_failure => cached: {
2250 // First, load the cached ZIR code, if any.
2251 log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{
2252 file.sub_file_path, want_local_cache, &digest,
2253 });
23962254
2397 // The exports this Decl performs will be re-discovered, so we remove them here2255 // We ask for a lock in order to coordinate with other zig processes.
2398 // prior to re-analysis.2256 // If another process is already working on this file, we will get the cached
2399 mod.deleteDeclExports(decl);2257 // version. Likewise if we're working on AstGen and another process asks for
2400 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.2258 // the cached file, they'll get it.
2401 for (decl.dependencies.items()) |entry| {2259 cache_file = zir_dir.openFile(&digest, .{ .lock = .Shared }) catch |err| switch (err) {
2402 const dep = entry.key;2260 error.PathAlreadyExists => unreachable, // opening for reading
2403 dep.removeDependant(decl);2261 error.NoSpaceLeft => unreachable, // opening for reading
2404 if (dep.dependants.items().len == 0 and !dep.deletion_flag) {2262 error.NotDir => unreachable, // no dir components
2405 // We don't perform a deletion here, because this Decl or another one2263 error.InvalidUtf8 => unreachable, // it's a hex encoded name
2406 // may end up referencing it before the update is complete.2264 error.BadPathName => unreachable, // it's a hex encoded name
2407 dep.deletion_flag = true;2265 error.NameTooLong => unreachable, // it's a fixed size name
2408 try mod.deletion_set.put(mod.gpa, dep, {});2266 error.PipeBusy => unreachable, // it's not a pipe
2409 }2267 error.WouldBlock => unreachable, // not asking for non-blocking I/O
2410 }2268
2411 decl.dependencies.clearRetainingCapacity();2269 error.SymLinkLoop,
2270 error.FileNotFound,
2271 error.Unexpected,
2272 => break :cached,
2273
2274 else => |e| return e, // Retryable errors are handled at callsite.
2275 };
24122276
2413 break :blk true;2277 // First we read the header to determine the lengths of arrays.
2414 },2278 const header = cache_file.?.reader().readStruct(Zir.Header) catch |err| switch (err) {
2279 // This can happen if Zig bails out of this function between creating
2280 // the cached file and writing it.
2281 error.EndOfStream => break :cached,
2282 else => |e| return e,
2283 };
2284 const unchanged_metadata =
2285 stat.size == header.stat_size and
2286 stat.mtime == header.stat_mtime and
2287 stat.inode == header.stat_inode;
2288
2289 if (!unchanged_metadata) {
2290 log.debug("AstGen cache stale: {s}", .{file.sub_file_path});
2291 break :cached;
2292 }
2293 log.debug("AstGen cache hit: {s} instructions_len={d}", .{
2294 file.sub_file_path, header.instructions_len,
2295 });
24152296
2416 .unreferenced => false,2297 var instructions: std.MultiArrayList(Zir.Inst) = .{};
2417 };2298 defer instructions.deinit(gpa);
24182299
2419 const type_changed = mod.astgenAndSemaDecl(decl) catch |err| switch (err) {2300 try instructions.setCapacity(gpa, header.instructions_len);
2420 error.OutOfMemory => return error.OutOfMemory,2301 instructions.len = header.instructions_len;
2421 error.AnalysisFail => return error.AnalysisFail,
2422 else => {
2423 decl.analysis = .sema_failure_retryable;
2424 try mod.failed_decls.ensureCapacity(mod.gpa, mod.failed_decls.items().len + 1);
2425 mod.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
2426 mod.gpa,
2427 decl.srcLoc(),
2428 "unable to analyze: {s}",
2429 .{@errorName(err)},
2430 ));
2431 return error.AnalysisFail;
2432 },
2433 };
24342302
2435 if (subsequent_analysis) {2303 var zir: Zir = .{
2436 // We may need to chase the dependants and re-analyze them.2304 .instructions = instructions.toOwnedSlice(),
2437 // However, if the decl is a function, and the type is the same, we do not need to.2305 .string_bytes = &.{},
2438 if (type_changed or decl.typed_value.most_recent.typed_value.val.tag() != .function) {2306 .extra = &.{},
2439 for (decl.dependants.items()) |entry| {2307 };
2440 const dep = entry.key;2308 var keep_zir = false;
2441 switch (dep.analysis) {2309 defer if (!keep_zir) zir.deinit(gpa);
2442 .unreferenced => unreachable,2310
2443 .in_progress => unreachable,2311 zir.string_bytes = try gpa.alloc(u8, header.string_bytes_len);
2444 .outdated => continue, // already queued for update2312 zir.extra = try gpa.alloc(u32, header.extra_len);
24452313
2446 .dependency_failure,2314 const safety_buffer = if (data_has_safety_tag)
2447 .sema_failure,2315 try gpa.alloc([8]u8, header.instructions_len)
2448 .sema_failure_retryable,2316 else
2449 .codegen_failure,2317 undefined;
2450 .codegen_failure_retryable,2318 defer if (data_has_safety_tag) gpa.free(safety_buffer);
2451 .complete,2319
2452 => if (dep.generation != mod.generation) {2320 const data_ptr = if (data_has_safety_tag)
2453 try mod.markOutdatedDecl(dep);2321 @ptrCast([*]u8, safety_buffer.ptr)
2454 },2322 else
2323 @ptrCast([*]u8, zir.instructions.items(.data).ptr);
2324
2325 var iovecs = [_]std.os.iovec{
2326 .{
2327 .iov_base = @ptrCast([*]u8, zir.instructions.items(.tag).ptr),
2328 .iov_len = header.instructions_len,
2329 },
2330 .{
2331 .iov_base = data_ptr,
2332 .iov_len = header.instructions_len * 8,
2333 },
2334 .{
2335 .iov_base = zir.string_bytes.ptr,
2336 .iov_len = header.string_bytes_len,
2337 },
2338 .{
2339 .iov_base = @ptrCast([*]u8, zir.extra.ptr),
2340 .iov_len = header.extra_len * 4,
2341 },
2342 };
2343 const amt_read = try cache_file.?.readvAll(&iovecs);
2344 const amt_expected = zir.instructions.len * 9 +
2345 zir.string_bytes.len +
2346 zir.extra.len * 4;
2347 if (amt_read != amt_expected) {
2348 log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path});
2349 zir.deinit(gpa);
2350 break :cached;
2351 }
2352 if (data_has_safety_tag) {
2353 const tags = zir.instructions.items(.tag);
2354 for (zir.instructions.items(.data)) |*data, i| {
2355 const union_tag = Zir.Inst.Tag.data_tags[@enumToInt(tags[i])];
2356 const as_struct = @ptrCast(*Stage1DataLayout, data);
2357 as_struct.* = .{
2358 .safety_tag = @enumToInt(union_tag),
2359 .data = safety_buffer[i],
2360 };
2455 }2361 }
2456 }2362 }
2457 }
2458 }
2459}
24602363
2461/// Returns `true` if the Decl type changed.2364 keep_zir = true;
2462/// Returns `true` if this is the first time analyzing the Decl.2365 file.zir = zir;
2463/// Returns `false` otherwise.2366 file.zir_loaded = true;
2464fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {2367 file.stat_size = header.stat_size;
2465 const tracy = trace(@src());2368 file.stat_inode = header.stat_inode;
2466 defer tracy.end();2369 file.stat_mtime = header.stat_mtime;
24672370 file.status = .success_zir;
2468 const tree = try mod.getAstTree(decl.container.file_scope);2371 log.debug("AstGen cached success: {s}", .{file.sub_file_path});
2469 const node_tags = tree.nodes.items(.tag);2372
2470 const node_datas = tree.nodes.items(.data);2373 // TODO don't report compile errors until Sema @importFile
2471 const decl_node = decl.src_node;2374 if (file.zir.hasCompileErrors()) {
2472 switch (node_tags[decl_node]) {2375 {
2473 .fn_decl => {2376 const lock = comp.mutex.acquire();
2474 const fn_proto = node_datas[decl_node].lhs;2377 defer lock.release();
2475 const body = node_datas[decl_node].rhs;2378 try mod.failed_files.putNoClobber(gpa, file, null);
2476 switch (node_tags[fn_proto]) {2379 }
2477 .fn_proto_simple => {2380 file.status = .astgen_failure;
2478 var params: [1]ast.Node.Index = undefined;2381 return error.AnalysisFail;
2479 return mod.astgenAndSemaFn(decl, tree.*, body, tree.fnProtoSimple(&params, fn_proto));
2480 },
2481 .fn_proto_multi => return mod.astgenAndSemaFn(decl, tree.*, body, tree.fnProtoMulti(fn_proto)),
2482 .fn_proto_one => {
2483 var params: [1]ast.Node.Index = undefined;
2484 return mod.astgenAndSemaFn(decl, tree.*, body, tree.fnProtoOne(&params, fn_proto));
2485 },
2486 .fn_proto => return mod.astgenAndSemaFn(decl, tree.*, body, tree.fnProto(fn_proto)),
2487 else => unreachable,
2488 }2382 }
2383 return;
2489 },2384 },
2490 .fn_proto_simple => {2385 .parse_failure, .astgen_failure, .success_zir => {
2491 var params: [1]ast.Node.Index = undefined;2386 const unchanged_metadata =
2492 return mod.astgenAndSemaFn(decl, tree.*, 0, tree.fnProtoSimple(&params, decl_node));2387 stat.size == file.stat_size and
2388 stat.mtime == file.stat_mtime and
2389 stat.inode == file.stat_inode;
2390
2391 if (unchanged_metadata) {
2392 log.debug("unmodified metadata of file: {s}", .{file.sub_file_path});
2393 return;
2394 }
2395
2396 log.debug("metadata changed: {s}", .{file.sub_file_path});
2493 },2397 },
2494 .fn_proto_multi => return mod.astgenAndSemaFn(decl, tree.*, 0, tree.fnProtoMulti(decl_node)),2398 }
2495 .fn_proto_one => {2399 if (cache_file) |f| {
2496 var params: [1]ast.Node.Index = undefined;2400 f.close();
2497 return mod.astgenAndSemaFn(decl, tree.*, 0, tree.fnProtoOne(&params, decl_node));2401 cache_file = null;
2402 }
2403 cache_file = zir_dir.createFile(&digest, .{ .lock = .Exclusive }) catch |err| switch (err) {
2404 error.NotDir => unreachable, // no dir components
2405 error.InvalidUtf8 => unreachable, // it's a hex encoded name
2406 error.BadPathName => unreachable, // it's a hex encoded name
2407 error.NameTooLong => unreachable, // it's a fixed size name
2408 error.PipeBusy => unreachable, // it's not a pipe
2409 error.WouldBlock => unreachable, // not asking for non-blocking I/O
2410 error.FileNotFound => unreachable, // no dir components
2411
2412 else => |e| {
2413 const pkg_path = file.pkg.root_src_directory.path orelse ".";
2414 const cache_path = cache_directory.path orelse ".";
2415 log.warn("unable to save cached ZIR code for {s}/{s} to {s}/{s}: {s}", .{
2416 pkg_path, file.sub_file_path, cache_path, &digest, @errorName(e),
2417 });
2418 return;
2498 },2419 },
2499 .fn_proto => return mod.astgenAndSemaFn(decl, tree.*, 0, tree.fnProto(decl_node)),2420 };
2500
2501 .global_var_decl => return mod.astgenAndSemaVarDecl(decl, tree.*, tree.globalVarDecl(decl_node)),
2502 .local_var_decl => return mod.astgenAndSemaVarDecl(decl, tree.*, tree.localVarDecl(decl_node)),
2503 .simple_var_decl => return mod.astgenAndSemaVarDecl(decl, tree.*, tree.simpleVarDecl(decl_node)),
2504 .aligned_var_decl => return mod.astgenAndSemaVarDecl(decl, tree.*, tree.alignedVarDecl(decl_node)),
2505
2506 .@"comptime" => {
2507 decl.analysis = .in_progress;
2508
2509 // A comptime decl does not store any value so we can just deinit this arena after analysis is done.
2510 var analysis_arena = std.heap.ArenaAllocator.init(mod.gpa);
2511 defer analysis_arena.deinit();
2512
2513 var code: zir.Code = blk: {
2514 var astgen = try AstGen.init(mod, decl, &analysis_arena.allocator);
2515 defer astgen.deinit();
2516
2517 var gen_scope: Scope.GenZir = .{
2518 .force_comptime = true,
2519 .parent = &decl.container.base,
2520 .astgen = &astgen,
2521 };
2522 defer gen_scope.instructions.deinit(mod.gpa);
2523
2524 const block_expr = node_datas[decl_node].lhs;
2525 _ = try AstGen.comptimeExpr(&gen_scope, &gen_scope.base, .none, block_expr);
2526 _ = try gen_scope.addBreak(.break_inline, 0, .void_value);
25272421
2528 const code = try gen_scope.finish();2422 mod.lockAndClearFileCompileError(file);
2529 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {2423
2530 code.dump(mod.gpa, "comptime_block", &gen_scope.base, 0) catch {};2424 // If the previous ZIR does not have compile errors, keep it around
2531 }2425 // in case parsing or new ZIR fails. In case of successful ZIR update
2532 break :blk code;2426 // at the end of this function we will free it.
2533 };2427 // We keep the previous ZIR loaded so that we can use it
2534 defer code.deinit(mod.gpa);2428 // for the update next time it does not have any compile errors. This avoids
25352429 // needlessly tossing out semantic analysis work when an error is
2536 var sema: Sema = .{2430 // temporarily introduced.
2537 .mod = mod,2431 if (file.zir_loaded and !file.zir.hasCompileErrors()) {
2538 .gpa = mod.gpa,2432 assert(file.prev_zir == null);
2539 .arena = &analysis_arena.allocator,2433 const prev_zir_ptr = try gpa.create(Zir);
2540 .code = code,2434 file.prev_zir = prev_zir_ptr;
2541 .inst_map = try analysis_arena.allocator.alloc(*ir.Inst, code.instructions.len),2435 prev_zir_ptr.* = file.zir;
2542 .owner_decl = decl,2436 file.zir = undefined;
2543 .func = null,2437 file.zir_loaded = false;
2544 .owner_func = null,2438 }
2545 .param_inst_list = &.{},2439 file.unload(gpa);
2546 };
2547 var block_scope: Scope.Block = .{
2548 .parent = null,
2549 .sema = &sema,
2550 .src_decl = decl,
2551 .instructions = .{},
2552 .inlining = null,
2553 .is_comptime = true,
2554 };
2555 defer block_scope.instructions.deinit(mod.gpa);
25562440
2557 _ = try sema.root(&block_scope);2441 if (stat.size > std.math.maxInt(u32))
2442 return error.FileTooBig;
25582443
2559 decl.analysis = .complete;2444 const source = try gpa.allocSentinel(u8, stat.size, 0);
2560 decl.generation = mod.generation;2445 defer if (!file.source_loaded) gpa.free(source);
2561 return true;2446 const amt = try source_file.readAll(source);
2562 },2447 if (amt != stat.size)
2563 .@"usingnamespace" => @panic("TODO usingnamespace decl"),2448 return error.UnexpectedEndOfFile;
2564 else => unreachable,
2565 }
2566}
25672449
2568fn astgenAndSemaFn(2450 file.stat_size = stat.size;
2569 mod: *Module,2451 file.stat_inode = stat.inode;
2570 decl: *Decl,2452 file.stat_mtime = stat.mtime;
2571 tree: ast.Tree,2453 file.source = source;
2572 body_node: ast.Node.Index,2454 file.source_loaded = true;
2573 fn_proto: ast.full.FnProto,
2574) !bool {
2575 const tracy = trace(@src());
2576 defer tracy.end();
25772455
2578 decl.analysis = .in_progress;2456 file.tree = try std.zig.parse(gpa, source);
2457 defer if (!file.tree_loaded) file.tree.deinit(gpa);
25792458
2580 const token_tags = tree.tokens.items(.tag);2459 if (file.tree.errors.len != 0) {
2460 const parse_err = file.tree.errors[0];
25812461
2582 // This arena allocator's memory is discarded at the end of this function. It is used2462 var msg = std.ArrayList(u8).init(gpa);
2583 // to determine the type of the function, and hence the type of the decl, which is needed2463 defer msg.deinit();
2584 // to complete the Decl analysis.
2585 var fn_type_scope_arena = std.heap.ArenaAllocator.init(mod.gpa);
2586 defer fn_type_scope_arena.deinit();
25872464
2588 var fn_type_astgen = try AstGen.init(mod, decl, &fn_type_scope_arena.allocator);2465 const token_starts = file.tree.tokens.items(.start);
2589 defer fn_type_astgen.deinit();
25902466
2591 var fn_type_scope: Scope.GenZir = .{2467 try file.tree.renderError(parse_err, msg.writer());
2592 .force_comptime = true,2468 const err_msg = try gpa.create(ErrorMsg);
2593 .parent = &decl.container.base,2469 err_msg.* = .{
2594 .astgen = &fn_type_astgen,2470 .src_loc = .{
2595 };2471 .file_scope = file,
2596 defer fn_type_scope.instructions.deinit(mod.gpa);2472 .parent_decl_node = 0,
25972473 .lazy = .{ .byte_abs = token_starts[parse_err.token] },
2598 decl.is_pub = fn_proto.visib_token != null;2474 },
25992475 .msg = msg.toOwnedSlice(),
2600 // The AST params array does not contain anytype and ... parameters.2476 };
2601 // We must iterate to count how many param types to allocate.
2602 const param_count = blk: {
2603 var count: usize = 0;
2604 var it = fn_proto.iterate(tree);
2605 while (it.next()) |param| {
2606 if (param.anytype_ellipsis3) |some| if (token_tags[some] == .ellipsis3) break;
2607 count += 1;
2608 }
2609 break :blk count;
2610 };
2611 const param_types = try fn_type_scope_arena.allocator.alloc(zir.Inst.Ref, param_count);
26122477
2613 var is_var_args = false;2478 {
2614 {2479 const lock = comp.mutex.acquire();
2615 var param_type_i: usize = 0;2480 defer lock.release();
2616 var it = fn_proto.iterate(tree);2481 try mod.failed_files.putNoClobber(gpa, file, err_msg);
2617 while (it.next()) |param| : (param_type_i += 1) {
2618 if (param.anytype_ellipsis3) |token| {
2619 switch (token_tags[token]) {
2620 .keyword_anytype => return mod.failTok(
2621 &fn_type_scope.base,
2622 token,
2623 "TODO implement anytype parameter",
2624 .{},
2625 ),
2626 .ellipsis3 => {
2627 is_var_args = true;
2628 break;
2629 },
2630 else => unreachable,
2631 }
2632 }
2633 const param_type_node = param.type_expr;
2634 assert(param_type_node != 0);
2635 param_types[param_type_i] =
2636 try AstGen.expr(&fn_type_scope, &fn_type_scope.base, .{ .ty = .type_type }, param_type_node);
2637 }
2638 assert(param_type_i == param_count);
2639 }
2640 if (fn_proto.lib_name) |lib_name_token| blk: {
2641 // TODO call std.zig.parseStringLiteral
2642 const lib_name_str = mem.trim(u8, tree.tokenSlice(lib_name_token), "\"");
2643 log.debug("extern fn symbol expected in lib '{s}'", .{lib_name_str});
2644 const target = mod.comp.getTarget();
2645 if (target_util.is_libc_lib_name(target, lib_name_str)) {
2646 if (!mod.comp.bin_file.options.link_libc) {
2647 return mod.failTok(
2648 &fn_type_scope.base,
2649 lib_name_token,
2650 "dependency on libc must be explicitly specified in the build command",
2651 .{},
2652 );
2653 }
2654 break :blk;
2655 }
2656 if (target_util.is_libcpp_lib_name(target, lib_name_str)) {
2657 if (!mod.comp.bin_file.options.link_libcpp) {
2658 return mod.failTok(
2659 &fn_type_scope.base,
2660 lib_name_token,
2661 "dependency on libc++ must be explicitly specified in the build command",
2662 .{},
2663 );
2664 }
2665 break :blk;
2666 }
2667 if (!target.isWasm() and !mod.comp.bin_file.options.pic) {
2668 return mod.failTok(
2669 &fn_type_scope.base,
2670 lib_name_token,
2671 "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
2672 .{ lib_name_str, lib_name_str },
2673 );
2674 }2482 }
2675 mod.comp.stage1AddLinkLib(lib_name_str) catch |err| {2483 file.status = .parse_failure;
2676 return mod.failTok(2484 return error.AnalysisFail;
2677 &fn_type_scope.base,
2678 lib_name_token,
2679 "unable to add link lib '{s}': {s}",
2680 .{ lib_name_str, @errorName(err) },
2681 );
2682 };
2683 }2485 }
2684 if (fn_proto.ast.align_expr != 0) {2486 file.tree_loaded = true;
2685 return mod.failNode(
2686 &fn_type_scope.base,
2687 fn_proto.ast.align_expr,
2688 "TODO implement function align expression",
2689 .{},
2690 );
2691 }
2692 if (fn_proto.ast.section_expr != 0) {
2693 return mod.failNode(
2694 &fn_type_scope.base,
2695 fn_proto.ast.section_expr,
2696 "TODO implement function section expression",
2697 .{},
2698 );
2699 }
2700
2701 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
2702 if (token_tags[maybe_bang] == .bang) {
2703 return mod.failTok(&fn_type_scope.base, maybe_bang, "TODO implement inferred error sets", .{});
2704 }
2705 const return_type_inst = try AstGen.expr(
2706 &fn_type_scope,
2707 &fn_type_scope.base,
2708 .{ .ty = .type_type },
2709 fn_proto.ast.return_type,
2710 );
27112487
2712 const is_extern = if (fn_proto.extern_export_token) |maybe_export_token|2488 file.zir = try AstGen.generate(gpa, file.tree);
2713 token_tags[maybe_export_token] == .keyword_extern2489 file.zir_loaded = true;
2490 file.status = .success_zir;
2491 log.debug("AstGen fresh success: {s}", .{file.sub_file_path});
2492
2493 const safety_buffer = if (data_has_safety_tag)
2494 try gpa.alloc([8]u8, file.zir.instructions.len)
2714 else2495 else
2715 false;2496 undefined;
27162497 defer if (data_has_safety_tag) gpa.free(safety_buffer);
2717 const cc: zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)2498 const data_ptr = if (data_has_safety_tag)
2718 // TODO instead of enum literal type, this needs to be the2499 @ptrCast([*]const u8, safety_buffer.ptr)
2719 // std.builtin.CallingConvention enum. We need to implement importing other files
2720 // and enums in order to fix this.
2721 try AstGen.comptimeExpr(
2722 &fn_type_scope,
2723 &fn_type_scope.base,
2724 .{ .ty = .enum_literal_type },
2725 fn_proto.ast.callconv_expr,
2726 )
2727 else if (is_extern) // note: https://github.com/ziglang/zig/issues/5269
2728 try fn_type_scope.addSmallStr(.enum_literal_small, "C")
2729 else2500 else
2730 .none;2501 @ptrCast([*]const u8, file.zir.instructions.items(.data).ptr);
27312502 if (data_has_safety_tag) {
2732 const fn_type_inst: zir.Inst.Ref = if (cc != .none) fn_type: {2503 // The `Data` union has a safety tag but in the file format we store it without.
2733 const tag: zir.Inst.Tag = if (is_var_args) .fn_type_cc_var_args else .fn_type_cc;2504 const tags = file.zir.instructions.items(.tag);
2734 break :fn_type try fn_type_scope.addFnTypeCc(tag, .{2505 for (file.zir.instructions.items(.data)) |*data, i| {
2735 .src_node = fn_proto.ast.proto_node,2506 const as_struct = @ptrCast(*const Stage1DataLayout, data);
2736 .ret_ty = return_type_inst,2507 safety_buffer[i] = as_struct.data;
2737 .param_types = param_types,2508 }
2738 .cc = cc,
2739 });
2740 } else fn_type: {
2741 const tag: zir.Inst.Tag = if (is_var_args) .fn_type_var_args else .fn_type;
2742 break :fn_type try fn_type_scope.addFnType(tag, .{
2743 .src_node = fn_proto.ast.proto_node,
2744 .ret_ty = return_type_inst,
2745 .param_types = param_types,
2746 });
2747 };
2748 _ = try fn_type_scope.addBreak(.break_inline, 0, fn_type_inst);
2749
2750 // We need the memory for the Type to go into the arena for the Decl
2751 var decl_arena = std.heap.ArenaAllocator.init(mod.gpa);
2752 errdefer decl_arena.deinit();
2753 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
2754
2755 var fn_type_code = try fn_type_scope.finish();
2756 defer fn_type_code.deinit(mod.gpa);
2757 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
2758 fn_type_code.dump(mod.gpa, "fn_type", &fn_type_scope.base, 0) catch {};
2759 }2509 }
27602510
2761 var fn_type_sema: Sema = .{2511 const header: Zir.Header = .{
2762 .mod = mod,2512 .instructions_len = @intCast(u32, file.zir.instructions.len),
2763 .gpa = mod.gpa,2513 .string_bytes_len = @intCast(u32, file.zir.string_bytes.len),
2764 .arena = &decl_arena.allocator,2514 .extra_len = @intCast(u32, file.zir.extra.len),
2765 .code = fn_type_code,2515
2766 .inst_map = try fn_type_scope_arena.allocator.alloc(*ir.Inst, fn_type_code.instructions.len),2516 .stat_size = stat.size,
2767 .owner_decl = decl,2517 .stat_inode = stat.inode,
2768 .func = null,2518 .stat_mtime = stat.mtime,
2769 .owner_func = null,
2770 .param_inst_list = &.{},
2771 };2519 };
2772 var block_scope: Scope.Block = .{2520 var iovecs = [_]std.os.iovec_const{
2773 .parent = null,2521 .{
2774 .sema = &fn_type_sema,2522 .iov_base = @ptrCast([*]const u8, &header),
2775 .src_decl = decl,2523 .iov_len = @sizeOf(Zir.Header),
2776 .instructions = .{},2524 },
2777 .inlining = null,2525 .{
2778 .is_comptime = true,2526 .iov_base = @ptrCast([*]const u8, file.zir.instructions.items(.tag).ptr),
2527 .iov_len = file.zir.instructions.len,
2528 },
2529 .{
2530 .iov_base = data_ptr,
2531 .iov_len = file.zir.instructions.len * 8,
2532 },
2533 .{
2534 .iov_base = file.zir.string_bytes.ptr,
2535 .iov_len = file.zir.string_bytes.len,
2536 },
2537 .{
2538 .iov_base = @ptrCast([*]const u8, file.zir.extra.ptr),
2539 .iov_len = file.zir.extra.len * 4,
2540 },
2541 };
2542 cache_file.?.writevAll(&iovecs) catch |err| {
2543 const pkg_path = file.pkg.root_src_directory.path orelse ".";
2544 const cache_path = cache_directory.path orelse ".";
2545 log.warn("unable to write cached ZIR code for {s}/{s} to {s}/{s}: {s}", .{
2546 pkg_path, file.sub_file_path, cache_path, &digest, @errorName(err),
2547 });
2779 };2548 };
2780 defer block_scope.instructions.deinit(mod.gpa);
2781
2782 const fn_type = try fn_type_sema.rootAsType(&block_scope);
2783 if (body_node == 0) {
2784 if (!is_extern) {
2785 return mod.failNode(&block_scope.base, fn_proto.ast.fn_token, "non-extern function has no body", .{});
2786 }
2787
2788 // Extern function.
2789 var type_changed = true;
2790 if (decl.typedValueManaged()) |tvm| {
2791 type_changed = !tvm.typed_value.ty.eql(fn_type);
2792
2793 tvm.deinit(mod.gpa);
2794 }
2795 const fn_val = try Value.Tag.extern_fn.create(&decl_arena.allocator, decl);
2796
2797 decl_arena_state.* = decl_arena.state;
2798 decl.typed_value = .{
2799 .most_recent = .{
2800 .typed_value = .{ .ty = fn_type, .val = fn_val },
2801 .arena = decl_arena_state,
2802 },
2803 };
2804 decl.analysis = .complete;
2805 decl.generation = mod.generation;
2806
2807 try mod.comp.bin_file.allocateDeclIndexes(decl);
2808 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl });
28092549
2810 if (type_changed and mod.emit_h != null) {2550 if (file.zir.hasCompileErrors()) {
2811 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl });2551 {
2552 const lock = comp.mutex.acquire();
2553 defer lock.release();
2554 try mod.failed_files.putNoClobber(gpa, file, null);
2812 }2555 }
28132556 file.status = .astgen_failure;
2814 return type_changed;2557 return error.AnalysisFail;
2815 }2558 }
28162559
2817 if (fn_type.fnIsVarArgs()) {2560 if (file.prev_zir) |prev_zir| {
2818 return mod.failNode(&block_scope.base, fn_proto.ast.fn_token, "non-extern function is variadic", .{});2561 // Iterate over all Namespace objects contained within this File, looking at the
2562 // previous and new ZIR together and update the references to point
2563 // to the new one. For example, Decl name, Decl zir_decl_index, and Namespace
2564 // decl_table keys need to get updated to point to the new memory, even if the
2565 // underlying source code is unchanged.
2566 // We do not need to hold any locks at this time because all the Decl and Namespace
2567 // objects being touched are specific to this File, and the only other concurrent
2568 // tasks are touching other File objects.
2569 try updateZirRefs(gpa, file, prev_zir.*);
2570 // At this point, `file.outdated_decls` and `file.deleted_decls` are populated,
2571 // and semantic analysis will deal with them properly.
2572 // No need to keep previous ZIR.
2573 prev_zir.deinit(gpa);
2574 gpa.destroy(prev_zir);
2575 file.prev_zir = null;
2576 } else if (file.root_decl) |root_decl| {
2577 // This is an update, but it is the first time the File has succeeded
2578 // ZIR. We must mark it outdated since we have already tried to
2579 // semantically analyze it.
2580 try file.outdated_decls.resize(gpa, 1);
2581 file.outdated_decls.items[0] = root_decl;
2819 }2582 }
2583}
28202584
2821 const new_func = try decl_arena.allocator.create(Fn);2585/// Patch ups:
2822 const fn_payload = try decl_arena.allocator.create(Value.Payload.Function);2586/// * Struct.zir_index
2587/// * Decl.zir_index
2588/// * Fn.zir_body_inst
2589/// * Decl.zir_decl_index
2590fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void {
2591 const new_zir = file.zir;
2592
2593 // Maps from old ZIR to new ZIR, struct_decl, enum_decl, etc. Any instruction which
2594 // creates a namespace, gets mapped from old to new here.
2595 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};
2596 defer inst_map.deinit(gpa);
2597 // Maps from old ZIR to new ZIR, the extra data index for the sub-decl item.
2598 // e.g. the thing that Decl.zir_decl_index points to.
2599 var extra_map: std.AutoHashMapUnmanaged(u32, u32) = .{};
2600 defer extra_map.deinit(gpa);
2601
2602 try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map, &extra_map);
2603
2604 // Walk the Decl graph, updating ZIR indexes, strings, and populating
2605 // the deleted and outdated lists.
2606
2607 var decl_stack: std.ArrayListUnmanaged(*Decl) = .{};
2608 defer decl_stack.deinit(gpa);
2609
2610 const root_decl = file.root_decl.?;
2611 try decl_stack.append(gpa, root_decl);
2612
2613 file.deleted_decls.clearRetainingCapacity();
2614 file.outdated_decls.clearRetainingCapacity();
2615
2616 // The root decl is always outdated; otherwise we would not have had
2617 // to re-generate ZIR for the File.
2618 try file.outdated_decls.append(gpa, root_decl);
2619
2620 while (decl_stack.popOrNull()) |decl| {
2621 // Anonymous decls and the root decl have this set to 0. We still need
2622 // to walk them but we do not need to modify this value.
2623 // Anonymous decls should not be marked outdated. They will be re-generated
2624 // if their owner decl is marked outdated.
2625 if (decl.zir_decl_index != 0) {
2626 const old_zir_decl_index = decl.zir_decl_index;
2627 const new_zir_decl_index = extra_map.get(old_zir_decl_index) orelse {
2628 log.debug("updateZirRefs {s}: delete {*} ({s})", .{
2629 file.sub_file_path, decl, decl.name,
2630 });
2631 try file.deleted_decls.append(gpa, decl);
2632 continue;
2633 };
2634 const old_hash = decl.contentsHashZir(old_zir);
2635 decl.zir_decl_index = new_zir_decl_index;
2636 const new_hash = decl.contentsHashZir(new_zir);
2637 if (!std.zig.srcHashEql(old_hash, new_hash)) {
2638 log.debug("updateZirRefs {s}: outdated {*} ({s}) {d} => {d}", .{
2639 file.sub_file_path, decl, decl.name, old_zir_decl_index, new_zir_decl_index,
2640 });
2641 try file.outdated_decls.append(gpa, decl);
2642 } else {
2643 log.debug("updateZirRefs {s}: unchanged {*} ({s}) {d} => {d}", .{
2644 file.sub_file_path, decl, decl.name, old_zir_decl_index, new_zir_decl_index,
2645 });
2646 }
2647 }
28232648
2824 const fn_zir: zir.Code = blk: {2649 if (!decl.owns_tv) continue;
2825 // We put the ZIR inside the Decl arena.
2826 var astgen = try AstGen.init(mod, decl, &decl_arena.allocator);
2827 astgen.ref_start_index = @intCast(u32, zir.Inst.Ref.typed_value_map.len + param_count);
2828 defer astgen.deinit();
28292650
2830 var gen_scope: Scope.GenZir = .{2651 if (decl.getStruct()) |struct_obj| {
2831 .force_comptime = false,2652 struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse {
2832 .parent = &decl.container.base,2653 try file.deleted_decls.append(gpa, decl);
2833 .astgen = &astgen,2654 continue;
2834 };
2835 defer gen_scope.instructions.deinit(mod.gpa);
2836
2837 // Iterate over the parameters. We put the param names as the first N
2838 // items inside `extra` so that debug info later can refer to the parameter names
2839 // even while the respective source code is unloaded.
2840 try astgen.extra.ensureCapacity(mod.gpa, param_count);
2841
2842 var params_scope = &gen_scope.base;
2843 var i: usize = 0;
2844 var it = fn_proto.iterate(tree);
2845 while (it.next()) |param| : (i += 1) {
2846 const name_token = param.name_token.?;
2847 const param_name = try mod.identifierTokenString(&gen_scope.base, name_token);
2848 const sub_scope = try decl_arena.allocator.create(Scope.LocalVal);
2849 sub_scope.* = .{
2850 .parent = params_scope,
2851 .gen_zir = &gen_scope,
2852 .name = param_name,
2853 // Implicit const list first, then implicit arg list.
2854 .inst = @intToEnum(zir.Inst.Ref, @intCast(u32, zir.Inst.Ref.typed_value_map.len + i)),
2855 .src = decl.tokSrcLoc(name_token),
2856 };2655 };
2857 params_scope = &sub_scope.base;
2858
2859 // Additionally put the param name into `string_bytes` and reference it with
2860 // `extra` so that we have access to the data in codegen, for debug info.
2861 const str_index = @intCast(u32, astgen.string_bytes.items.len);
2862 astgen.extra.appendAssumeCapacity(str_index);
2863 const used_bytes = astgen.string_bytes.items.len;
2864 try astgen.string_bytes.ensureCapacity(mod.gpa, used_bytes + param_name.len + 1);
2865 astgen.string_bytes.appendSliceAssumeCapacity(param_name);
2866 astgen.string_bytes.appendAssumeCapacity(0);
2867 }2656 }
28682657
2869 _ = try AstGen.expr(&gen_scope, params_scope, .none, body_node);2658 if (decl.getUnion()) |union_obj| {
2659 union_obj.zir_index = inst_map.get(union_obj.zir_index) orelse {
2660 try file.deleted_decls.append(gpa, decl);
2661 continue;
2662 };
2663 }
28702664
2871 if (gen_scope.instructions.items.len == 0 or2665 if (decl.getFunction()) |func| {
2872 !astgen.instructions.items(.tag)[gen_scope.instructions.items.len - 1]2666 func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {
2873 .isNoReturn())2667 try file.deleted_decls.append(gpa, decl);
2874 {2668 continue;
2875 // astgen uses result location semantics to coerce return operands.2669 };
2876 // Since we are adding the return instruction here, we must handle the coercion.
2877 // We do this by using the `ret_coerce` instruction.
2878 _ = try gen_scope.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
2879 }2670 }
28802671
2881 const code = try gen_scope.finish();2672 if (decl.getInnerNamespace()) |namespace| {
2882 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {2673 for (namespace.decls.items()) |entry| {
2883 code.dump(mod.gpa, "fn_body", &gen_scope.base, param_count) catch {};2674 const sub_decl = entry.value;
2675 try decl_stack.append(gpa, sub_decl);
2676 }
2677 for (namespace.anon_decls.items()) |entry| {
2678 const sub_decl = entry.key;
2679 try decl_stack.append(gpa, sub_decl);
2680 }
2884 }2681 }
2682 }
2683}
28852684
2886 break :blk code;2685pub fn mapOldZirToNew(
2686 gpa: *Allocator,
2687 old_zir: Zir,
2688 new_zir: Zir,
2689 inst_map: *std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index),
2690 extra_map: *std.AutoHashMapUnmanaged(u32, u32),
2691) Allocator.Error!void {
2692 // Contain ZIR indexes of declaration instructions.
2693 const MatchedZirDecl = struct {
2694 old_inst: Zir.Inst.Index,
2695 new_inst: Zir.Inst.Index,
2887 };2696 };
2697 var match_stack: std.ArrayListUnmanaged(MatchedZirDecl) = .{};
2698 defer match_stack.deinit(gpa);
28882699
2889 const is_inline = fn_type.fnCallingConvention() == .Inline;2700 const old_main_struct_inst = old_zir.getMainStruct();
2890 const anal_state: Fn.Analysis = if (is_inline) .inline_only else .queued;2701 const new_main_struct_inst = new_zir.getMainStruct();
28912702
2892 new_func.* = .{2703 try match_stack.append(gpa, .{
2893 .state = anal_state,2704 .old_inst = old_main_struct_inst,
2894 .zir = fn_zir,2705 .new_inst = new_main_struct_inst,
2895 .body = undefined,2706 });
2896 .owner_decl = decl,
2897 };
2898 fn_payload.* = .{
2899 .base = .{ .tag = .function },
2900 .data = new_func,
2901 };
29022707
2903 var prev_type_has_bits = false;2708 var old_decls = std.ArrayList(Zir.Inst.Index).init(gpa);
2904 var prev_is_inline = false;2709 defer old_decls.deinit();
2905 var type_changed = true;2710 var new_decls = std.ArrayList(Zir.Inst.Index).init(gpa);
29062711 defer new_decls.deinit();
2907 if (decl.typedValueManaged()) |tvm| {
2908 prev_type_has_bits = tvm.typed_value.ty.hasCodeGenBits();
2909 type_changed = !tvm.typed_value.ty.eql(fn_type);
2910 if (tvm.typed_value.val.castTag(.function)) |payload| {
2911 const prev_func = payload.data;
2912 prev_is_inline = prev_func.state == .inline_only;
2913 prev_func.deinit(mod.gpa);
2914 }
29152712
2916 tvm.deinit(mod.gpa);2713 while (match_stack.popOrNull()) |match_item| {
2917 }2714 try inst_map.put(gpa, match_item.old_inst, match_item.new_inst);
29182715
2919 decl_arena_state.* = decl_arena.state;2716 // Maps name to extra index of decl sub item.
2920 decl.typed_value = .{2717 var decl_map: std.StringHashMapUnmanaged(u32) = .{};
2921 .most_recent = .{2718 defer decl_map.deinit(gpa);
2922 .typed_value = .{2719
2923 .ty = fn_type,2720 {
2924 .val = Value.initPayload(&fn_payload.base),2721 var old_decl_it = old_zir.declIterator(match_item.old_inst);
2925 },2722 while (old_decl_it.next()) |old_decl| {
2926 .arena = decl_arena_state,2723 try decl_map.put(gpa, old_decl.name, old_decl.sub_index);
2927 },2724 }
2928 };
2929 decl.analysis = .complete;
2930 decl.generation = mod.generation;
2931
2932 if (!is_inline and fn_type.hasCodeGenBits()) {
2933 // We don't fully codegen the decl until later, but we do need to reserve a global
2934 // offset table index for it. This allows us to codegen decls out of dependency order,
2935 // increasing how many computations can be done in parallel.
2936 try mod.comp.bin_file.allocateDeclIndexes(decl);
2937 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl });
2938 if (type_changed and mod.emit_h != null) {
2939 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl });
2940 }2725 }
2941 } else if (!prev_is_inline and prev_type_has_bits) {
2942 mod.comp.bin_file.freeDecl(decl);
2943 }
29442726
2945 if (fn_proto.extern_export_token) |maybe_export_token| {2727 var new_decl_it = new_zir.declIterator(match_item.new_inst);
2946 if (token_tags[maybe_export_token] == .keyword_export) {2728 while (new_decl_it.next()) |new_decl| {
2947 if (is_inline) {2729 const old_extra_index = decl_map.get(new_decl.name) orelse continue;
2948 return mod.failTok(2730 const new_extra_index = new_decl.sub_index;
2949 &block_scope.base,2731 try extra_map.put(gpa, old_extra_index, new_extra_index);
2950 maybe_export_token,2732
2951 "export of inline function",2733 try old_zir.findDecls(&old_decls, old_extra_index);
2952 .{},2734 try new_zir.findDecls(&new_decls, new_extra_index);
2953 );2735 var i: usize = 0;
2736 while (true) : (i += 1) {
2737 if (i >= old_decls.items.len) break;
2738 if (i >= new_decls.items.len) break;
2739 try match_stack.append(gpa, .{
2740 .old_inst = old_decls.items[i],
2741 .new_inst = new_decls.items[i],
2742 });
2954 }2743 }
2955 const export_src = decl.tokSrcLoc(maybe_export_token);
2956 const name = tree.tokenSlice(fn_proto.name_token.?); // TODO identifierTokenString
2957 // The scope needs to have the decl in it.
2958 try mod.analyzeExport(&block_scope.base, export_src, name, decl);
2959 }2744 }
2960 }2745 }
2961 return type_changed or is_inline != prev_is_inline;
2962}2746}
29632747
2964fn astgenAndSemaVarDecl(2748pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) InnerError!void {
2965 mod: *Module,
2966 decl: *Decl,
2967 tree: ast.Tree,
2968 var_decl: ast.full.VarDecl,
2969) !bool {
2970 const tracy = trace(@src());2749 const tracy = trace(@src());
2971 defer tracy.end();2750 defer tracy.end();
29722751
2973 decl.analysis = .in_progress;2752 const subsequent_analysis = switch (decl.analysis) {
2974 decl.is_pub = var_decl.visib_token != null;2753 .in_progress => unreachable,
2975
2976 const token_tags = tree.tokens.items(.tag);
29772754
2978 // We need the memory for the Type to go into the arena for the Decl2755 .file_failure,
2979 var decl_arena = std.heap.ArenaAllocator.init(mod.gpa);2756 .sema_failure,
2980 errdefer decl_arena.deinit();2757 .sema_failure_retryable,
2981 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);2758 .codegen_failure,
2759 .dependency_failure,
2760 .codegen_failure_retryable,
2761 => return error.AnalysisFail,
29822762
2983 // Used for simple error reporting.2763 .complete => return,
2984 var decl_scope: Scope.DeclRef = .{ .decl = decl };
29852764
2986 const is_extern = blk: {2765 .outdated => blk: {
2987 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;2766 log.debug("re-analyzing {*} ({s})", .{ decl, decl.name });
2988 break :blk token_tags[maybe_extern_token] == .keyword_extern;
2989 };
29902767
2991 if (var_decl.lib_name) |lib_name| {2768 // The exports this Decl performs will be re-discovered, so we remove them here
2992 assert(is_extern);2769 // prior to re-analysis.
2993 return mod.failTok(&decl_scope.base, lib_name, "TODO implement function library name", .{});2770 mod.deleteDeclExports(decl);
2994 }2771 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.
2995 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;2772 for (decl.dependencies.items()) |entry| {
2996 const is_threadlocal = if (var_decl.threadlocal_token) |some| blk: {2773 const dep = entry.key;
2997 if (!is_mutable) {2774 dep.removeDependant(decl);
2998 return mod.failTok(&decl_scope.base, some, "threadlocal variable cannot be constant", .{});2775 if (dep.dependants.count() == 0 and !dep.deletion_flag) {
2999 }2776 log.debug("insert {*} ({s}) dependant {*} ({s}) into deletion set", .{
3000 break :blk true;2777 decl, decl.name, dep, dep.name,
3001 } else false;2778 });
3002 assert(var_decl.comptime_token == null);2779 // We don't perform a deletion here, because this Decl or another one
3003 if (var_decl.ast.align_node != 0) {2780 // may end up referencing it before the update is complete.
3004 return mod.failNode(2781 dep.deletion_flag = true;
3005 &decl_scope.base,2782 try mod.deletion_set.put(mod.gpa, dep, {});
3006 var_decl.ast.align_node,2783 }
3007 "TODO implement function align expression",2784 }
3008 .{},2785 decl.dependencies.clearRetainingCapacity();
3009 );
3010 }
3011 if (var_decl.ast.section_node != 0) {
3012 return mod.failNode(
3013 &decl_scope.base,
3014 var_decl.ast.section_node,
3015 "TODO implement function section expression",
3016 .{},
3017 );
3018 }
3019
3020 const var_info: struct { ty: Type, val: ?Value } = if (var_decl.ast.init_node != 0) vi: {
3021 if (is_extern) {
3022 return mod.failNode(
3023 &decl_scope.base,
3024 var_decl.ast.init_node,
3025 "extern variables have no initializers",
3026 .{},
3027 );
3028 }
30292786
3030 var gen_scope_arena = std.heap.ArenaAllocator.init(mod.gpa);2787 break :blk true;
3031 defer gen_scope_arena.deinit();2788 },
30322789
3033 var astgen = try AstGen.init(mod, decl, &gen_scope_arena.allocator);2790 .unreferenced => false,
3034 defer astgen.deinit();2791 };
30352792
3036 var gen_scope: Scope.GenZir = .{2793 const type_changed = mod.semaDecl(decl) catch |err| switch (err) {
3037 .force_comptime = true,2794 error.AnalysisFail => {
3038 .parent = &decl.container.base,2795 if (decl.analysis == .in_progress) {
3039 .astgen = &astgen,2796 // If this decl caused the compile error, the analysis field would
3040 };2797 // be changed to indicate it was this Decl's fault. Because this
3041 defer gen_scope.instructions.deinit(mod.gpa);2798 // did not happen, we infer here that it was a dependency failure.
2799 decl.analysis = .dependency_failure;
2800 }
2801 return error.AnalysisFail;
2802 },
2803 else => {
2804 decl.analysis = .sema_failure_retryable;
2805 try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1);
2806 mod.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
2807 mod.gpa,
2808 decl.srcLoc(),
2809 "unable to analyze: {s}",
2810 .{@errorName(err)},
2811 ));
2812 return error.AnalysisFail;
2813 },
2814 };
30422815
3043 const init_result_loc: AstGen.ResultLoc = if (var_decl.ast.type_node != 0) .{2816 if (subsequent_analysis) {
3044 .ty = try AstGen.expr(&gen_scope, &gen_scope.base, .{ .ty = .type_type }, var_decl.ast.type_node),2817 // We may need to chase the dependants and re-analyze them.
3045 } else .none;2818 // However, if the decl is a function, and the type is the same, we do not need to.
2819 if (type_changed or decl.ty.zigTypeTag() != .Fn) {
2820 for (decl.dependants.items()) |entry| {
2821 const dep = entry.key;
2822 switch (dep.analysis) {
2823 .unreferenced => unreachable,
2824 .in_progress => continue, // already doing analysis, ok
2825 .outdated => continue, // already queued for update
30462826
3047 const init_inst = try AstGen.comptimeExpr(2827 .file_failure,
3048 &gen_scope,2828 .dependency_failure,
3049 &gen_scope.base,2829 .sema_failure,
3050 init_result_loc,2830 .sema_failure_retryable,
3051 var_decl.ast.init_node,2831 .codegen_failure,
3052 );2832 .codegen_failure_retryable,
3053 _ = try gen_scope.addBreak(.break_inline, 0, init_inst);2833 .complete,
3054 var code = try gen_scope.finish();2834 => if (dep.generation != mod.generation) {
3055 defer code.deinit(mod.gpa);2835 try mod.markOutdatedDecl(dep);
3056 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {2836 },
3057 code.dump(mod.gpa, "var_init", &gen_scope.base, 0) catch {};2837 }
2838 }
3058 }2839 }
2840 }
2841}
30592842
3060 var sema: Sema = .{2843pub fn semaPkg(mod: *Module, pkg: *Package) !void {
3061 .mod = mod,2844 const file = (try mod.importPkg(mod.root_pkg, pkg)).file;
3062 .gpa = mod.gpa,2845 return mod.semaFile(file);
3063 .arena = &gen_scope_arena.allocator,2846}
3064 .code = code,
3065 .inst_map = try gen_scope_arena.allocator.alloc(*ir.Inst, code.instructions.len),
3066 .owner_decl = decl,
3067 .func = null,
3068 .owner_func = null,
3069 .param_inst_list = &.{},
3070 };
3071 var block_scope: Scope.Block = .{
3072 .parent = null,
3073 .sema = &sema,
3074 .src_decl = decl,
3075 .instructions = .{},
3076 .inlining = null,
3077 .is_comptime = true,
3078 };
3079 defer block_scope.instructions.deinit(mod.gpa);
30802847
3081 const init_inst_zir_ref = try sema.rootAsRef(&block_scope);2848/// Regardless of the file status, will create a `Decl` so that we
3082 // The result location guarantees the type coercion.2849/// can track dependencies and re-analyze when the file becomes outdated.
3083 const analyzed_init_inst = try sema.resolveInst(init_inst_zir_ref);2850pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
3084 // The is_comptime in the Scope.Block guarantees the result is comptime-known.2851 const tracy = trace(@src());
3085 const val = analyzed_init_inst.value().?;2852 defer tracy.end();
30862853
3087 break :vi .{2854 if (file.root_decl != null) return;
3088 .ty = try analyzed_init_inst.ty.copy(&decl_arena.allocator),
3089 .val = try val.copy(&decl_arena.allocator),
3090 };
3091 } else if (!is_extern) {
3092 return mod.failTok(
3093 &decl_scope.base,
3094 var_decl.ast.mut_token,
3095 "variables must be initialized",
3096 .{},
3097 );
3098 } else if (var_decl.ast.type_node != 0) vi: {
3099 var type_scope_arena = std.heap.ArenaAllocator.init(mod.gpa);
3100 defer type_scope_arena.deinit();
3101
3102 var astgen = try AstGen.init(mod, decl, &type_scope_arena.allocator);
3103 defer astgen.deinit();
3104
3105 var type_scope: Scope.GenZir = .{
3106 .force_comptime = true,
3107 .parent = &decl.container.base,
3108 .astgen = &astgen,
3109 };
3110 defer type_scope.instructions.deinit(mod.gpa);
31112855
3112 const var_type = try AstGen.typeExpr(&type_scope, &type_scope.base, var_decl.ast.type_node);2856 const gpa = mod.gpa;
3113 _ = try type_scope.addBreak(.break_inline, 0, var_type);2857 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
2858 errdefer new_decl_arena.deinit();
2859
2860 const struct_obj = try new_decl_arena.allocator.create(Module.Struct);
2861 const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);
2862 const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty);
2863 struct_obj.* = .{
2864 .owner_decl = undefined, // set below
2865 .fields = .{},
2866 .node_offset = 0, // it's the struct for the root file
2867 .zir_index = undefined, // set below
2868 .layout = .Auto,
2869 .status = .none,
2870 .namespace = .{
2871 .parent = null,
2872 .ty = struct_ty,
2873 .file_scope = file,
2874 },
2875 };
2876 const new_decl = try mod.allocateNewDecl(&struct_obj.namespace, 0);
2877 file.root_decl = new_decl;
2878 struct_obj.owner_decl = new_decl;
2879 new_decl.src_line = 0;
2880 new_decl.name = try file.fullyQualifiedNameZ(gpa);
2881 new_decl.is_pub = true;
2882 new_decl.is_exported = false;
2883 new_decl.has_align = false;
2884 new_decl.has_linksection = false;
2885 new_decl.ty = struct_ty;
2886 new_decl.val = struct_val;
2887 new_decl.has_tv = true;
2888 new_decl.owns_tv = true;
2889 new_decl.analysis = .in_progress;
2890 new_decl.generation = mod.generation;
31142891
3115 var code = try type_scope.finish();2892 if (file.status == .success_zir) {
3116 defer code.deinit(mod.gpa);2893 assert(file.zir_loaded);
3117 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {2894 const main_struct_inst = file.zir.getMainStruct();
3118 code.dump(mod.gpa, "var_type", &type_scope.base, 0) catch {};2895 struct_obj.zir_index = main_struct_inst;
3119 }2896
2897 var sema_arena = std.heap.ArenaAllocator.init(gpa);
2898 defer sema_arena.deinit();
31202899
3121 var sema: Sema = .{2900 var sema: Sema = .{
3122 .mod = mod,2901 .mod = mod,
3123 .gpa = mod.gpa,2902 .gpa = gpa,
3124 .arena = &type_scope_arena.allocator,2903 .arena = &sema_arena.allocator,
3125 .code = code,2904 .code = file.zir,
3126 .inst_map = try type_scope_arena.allocator.alloc(*ir.Inst, code.instructions.len),2905 .owner_decl = new_decl,
3127 .owner_decl = decl,2906 .namespace = &struct_obj.namespace,
3128 .func = null,2907 .func = null,
3129 .owner_func = null,2908 .owner_func = null,
3130 .param_inst_list = &.{},2909 .param_inst_list = &.{},
3131 };2910 };
2911 defer sema.deinit();
3132 var block_scope: Scope.Block = .{2912 var block_scope: Scope.Block = .{
3133 .parent = null,2913 .parent = null,
3134 .sema = &sema,2914 .sema = &sema,
3135 .src_decl = decl,2915 .src_decl = new_decl,
3136 .instructions = .{},2916 .instructions = .{},
3137 .inlining = null,2917 .inlining = null,
3138 .is_comptime = true,2918 .is_comptime = true,
3139 };2919 };
3140 defer block_scope.instructions.deinit(mod.gpa);2920 defer block_scope.instructions.deinit(gpa);
3141
3142 const ty = try sema.rootAsType(&block_scope);
31432921
3144 break :vi .{2922 if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_obj)) |_| {
3145 .ty = try ty.copy(&decl_arena.allocator),2923 new_decl.analysis = .complete;
3146 .val = null,2924 } else |err| switch (err) {
3147 };2925 error.OutOfMemory => return error.OutOfMemory,
2926 error.AnalysisFail => {},
2927 }
3148 } else {2928 } else {
3149 return mod.failTok(2929 new_decl.analysis = .file_failure;
3150 &decl_scope.base,
3151 var_decl.ast.mut_token,
3152 "unable to infer variable type",
3153 .{},
3154 );
3155 };
3156
3157 if (is_mutable and !var_info.ty.isValidVarType(is_extern)) {
3158 return mod.failTok(
3159 &decl_scope.base,
3160 var_decl.ast.mut_token,
3161 "variable of type '{}' must be const",
3162 .{var_info.ty},
3163 );
3164 }2930 }
31652931
3166 var type_changed = true;2932 try new_decl.finalizeNewArena(&new_decl_arena);
3167 if (decl.typedValueManaged()) |tvm| {2933}
3168 type_changed = !tvm.typed_value.ty.eql(var_info.ty);
31692934
3170 tvm.deinit(mod.gpa);2935/// Returns `true` if the Decl type changed.
3171 }2936/// Returns `true` if this is the first time analyzing the Decl.
2937/// Returns `false` otherwise.
2938fn semaDecl(mod: *Module, decl: *Decl) !bool {
2939 const tracy = trace(@src());
2940 defer tracy.end();
31722941
3173 const new_variable = try decl_arena.allocator.create(Var);2942 if (decl.namespace.file_scope.status != .success_zir) {
3174 new_variable.* = .{2943 return error.AnalysisFail;
3175 .owner_decl = decl,
3176 .init = var_info.val orelse undefined,
3177 .is_extern = is_extern,
3178 .is_mutable = is_mutable,
3179 .is_threadlocal = is_threadlocal,
3180 };
3181 const var_val = try Value.Tag.variable.create(&decl_arena.allocator, new_variable);
3182
3183 decl_arena_state.* = decl_arena.state;
3184 decl.typed_value = .{
3185 .most_recent = .{
3186 .typed_value = .{
3187 .ty = var_info.ty,
3188 .val = var_val,
3189 },
3190 .arena = decl_arena_state,
3191 },
3192 };
3193 decl.analysis = .complete;
3194 decl.generation = mod.generation;
3195
3196 if (var_decl.extern_export_token) |maybe_export_token| {
3197 if (token_tags[maybe_export_token] == .keyword_export) {
3198 const export_src = decl.tokSrcLoc(maybe_export_token);
3199 const name_token = var_decl.ast.mut_token + 1;
3200 const name = tree.tokenSlice(name_token); // TODO identifierTokenString
3201 // The scope needs to have the decl in it.
3202 try mod.analyzeExport(&decl_scope.base, export_src, name, decl);
3203 }
3204 }2944 }
3205 return type_changed;
3206}
32072945
3208/// Returns the depender's index of the dependee.2946 const gpa = mod.gpa;
3209pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !u32 {2947 const zir = decl.namespace.file_scope.zir;
3210 try depender.dependencies.ensureCapacity(mod.gpa, depender.dependencies.count() + 1);2948 const zir_datas = zir.instructions.items(.data);
3211 try dependee.dependants.ensureCapacity(mod.gpa, dependee.dependants.count() + 1);
32122949
3213 if (dependee.deletion_flag) {2950 decl.analysis = .in_progress;
3214 dependee.deletion_flag = false;
3215 mod.deletion_set.removeAssertDiscard(dependee);
3216 }
32172951
3218 dependee.dependants.putAssumeCapacity(depender, {});2952 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
3219 const gop = depender.dependencies.getOrPutAssumeCapacity(dependee);2953 defer analysis_arena.deinit();
3220 return @intCast(u32, gop.index);
3221}
32222954
3223pub fn getAstTree(mod: *Module, root_scope: *Scope.File) !*const ast.Tree {2955 var sema: Sema = .{
3224 const tracy = trace(@src());2956 .mod = mod,
3225 defer tracy.end();2957 .gpa = gpa,
2958 .arena = &analysis_arena.allocator,
2959 .code = zir,
2960 .owner_decl = decl,
2961 .namespace = decl.namespace,
2962 .func = null,
2963 .owner_func = null,
2964 .param_inst_list = &.{},
2965 };
2966 defer sema.deinit();
2967
2968 if (decl.isRoot()) {
2969 log.debug("semaDecl root {*} ({s})", .{ decl, decl.name });
2970 const main_struct_inst = zir.getMainStruct();
2971 const struct_obj = decl.getStruct().?;
2972 // This might not have gotten set in `semaFile` if the first time had
2973 // a ZIR failure, so we set it here in case.
2974 struct_obj.zir_index = main_struct_inst;
2975 try sema.analyzeStructDecl(decl, main_struct_inst, struct_obj);
2976 decl.analysis = .complete;
2977 decl.generation = mod.generation;
2978 return false;
2979 }
32262980
3227 switch (root_scope.status) {2981 var block_scope: Scope.Block = .{
3228 .never_loaded, .unloaded_success => {2982 .parent = null,
3229 try mod.failed_files.ensureCapacity(mod.gpa, mod.failed_files.items().len + 1);2983 .sema = &sema,
2984 .src_decl = decl,
2985 .instructions = .{},
2986 .inlining = null,
2987 .is_comptime = true,
2988 };
2989 defer block_scope.instructions.deinit(gpa);
2990
2991 const zir_block_index = decl.zirBlockIndex();
2992 const inst_data = zir_datas[zir_block_index].pl_node;
2993 const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index);
2994 const body = zir.extra[extra.end..][0..extra.data.body_len];
2995 const break_index = try sema.analyzeBody(&block_scope, body);
2996 const result_ref = zir_datas[break_index].@"break".operand;
2997 const src: LazySrcLoc = .{ .node_offset = 0 };
2998 const decl_tv = try sema.resolveInstConst(&block_scope, src, result_ref);
2999 const align_val = blk: {
3000 const align_ref = decl.zirAlignRef();
3001 if (align_ref == .none) break :blk Value.initTag(.null_value);
3002 break :blk (try sema.resolveInstConst(&block_scope, src, align_ref)).val;
3003 };
3004 const linksection_val = blk: {
3005 const linksection_ref = decl.zirLinksectionRef();
3006 if (linksection_ref == .none) break :blk Value.initTag(.null_value);
3007 break :blk (try sema.resolveInstConst(&block_scope, src, linksection_ref)).val;
3008 };
32303009
3231 const source = try root_scope.getSource(mod);3010 // We need the memory for the Type to go into the arena for the Decl
3011 var decl_arena = std.heap.ArenaAllocator.init(gpa);
3012 errdefer decl_arena.deinit();
3013 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
32323014
3233 var keep_tree = false;3015 if (decl_tv.val.castTag(.function)) |fn_payload| {
3234 root_scope.tree = try std.zig.parse(mod.gpa, source);3016 var prev_type_has_bits = false;
3235 defer if (!keep_tree) root_scope.tree.deinit(mod.gpa);3017 var prev_is_inline = false;
3018 var type_changed = true;
32363019
3237 const tree = &root_scope.tree;3020 if (decl.has_tv) {
3021 prev_type_has_bits = decl.ty.hasCodeGenBits();
3022 type_changed = !decl.ty.eql(decl_tv.ty);
3023 if (decl.getFunction()) |prev_func| {
3024 prev_is_inline = prev_func.state == .inline_only;
3025 }
3026 decl.clearValues(gpa);
3027 }
32383028
3239 if (tree.errors.len != 0) {3029 decl.ty = try decl_tv.ty.copy(&decl_arena.allocator);
3240 const parse_err = tree.errors[0];3030 decl.val = try decl_tv.val.copy(&decl_arena.allocator);
3031 decl.align_val = try align_val.copy(&decl_arena.allocator);
3032 decl.linksection_val = try linksection_val.copy(&decl_arena.allocator);
3033 decl.has_tv = true;
3034 decl.owns_tv = fn_payload.data.owner_decl == decl;
3035 decl_arena_state.* = decl_arena.state;
3036 decl.value_arena = decl_arena_state;
3037 decl.analysis = .complete;
3038 decl.generation = mod.generation;
32413039
3242 var msg = std.ArrayList(u8).init(mod.gpa);3040 const is_inline = decl_tv.ty.fnCallingConvention() == .Inline;
3243 defer msg.deinit();3041 if (!is_inline and decl_tv.ty.hasCodeGenBits()) {
3042 // We don't fully codegen the decl until later, but we do need to reserve a global
3043 // offset table index for it. This allows us to codegen decls out of dependency order,
3044 // increasing how many computations can be done in parallel.
3045 try mod.comp.bin_file.allocateDeclIndexes(decl);
3046 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl });
3047 if (type_changed and mod.emit_h != null) {
3048 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl });
3049 }
3050 } else if (!prev_is_inline and prev_type_has_bits) {
3051 mod.comp.bin_file.freeDecl(decl);
3052 }
32443053
3245 const token_starts = tree.tokens.items(.start);3054 if (decl.is_exported) {
3055 const export_src = src; // TODO make this point at `export` token
3056 if (is_inline) {
3057 return mod.fail(&block_scope.base, export_src, "export of inline function", .{});
3058 }
3059 // The scope needs to have the decl in it.
3060 try mod.analyzeExport(&block_scope.base, export_src, mem.spanZ(decl.name), decl);
3061 }
3062 return type_changed or is_inline != prev_is_inline;
3063 } else {
3064 var type_changed = true;
3065 if (decl.has_tv) {
3066 type_changed = !decl.ty.eql(decl_tv.ty);
3067 decl.clearValues(gpa);
3068 }
32463069
3247 try tree.renderError(parse_err, msg.writer());3070 decl.owns_tv = false;
3248 const err_msg = try mod.gpa.create(ErrorMsg);3071 var queue_linker_work = false;
3249 err_msg.* = .{3072 if (decl_tv.val.castTag(.variable)) |payload| {
3250 .src_loc = .{3073 const variable = payload.data;
3251 .container = .{ .file_scope = root_scope },3074 if (variable.owner_decl == decl) {
3252 .lazy = .{ .byte_abs = token_starts[parse_err.token] },3075 decl.owns_tv = true;
3253 },3076 queue_linker_work = true;
3254 .msg = msg.toOwnedSlice(),
3255 };
32563077
3257 mod.failed_files.putAssumeCapacityNoClobber(root_scope, err_msg);3078 const copied_init = try variable.init.copy(&decl_arena.allocator);
3258 root_scope.status = .unloaded_parse_failure;3079 variable.init = copied_init;
3259 return error.AnalysisFail;
3260 }3080 }
3081 } else if (decl_tv.val.castTag(.extern_fn)) |payload| {
3082 const owner_decl = payload.data;
3083 if (decl == owner_decl) {
3084 decl.owns_tv = true;
3085 queue_linker_work = true;
3086 }
3087 }
3088
3089 decl.ty = try decl_tv.ty.copy(&decl_arena.allocator);
3090 decl.val = try decl_tv.val.copy(&decl_arena.allocator);
3091 decl.align_val = try align_val.copy(&decl_arena.allocator);
3092 decl.linksection_val = try linksection_val.copy(&decl_arena.allocator);
3093 decl.has_tv = true;
3094 decl_arena_state.* = decl_arena.state;
3095 decl.value_arena = decl_arena_state;
3096 decl.analysis = .complete;
3097 decl.generation = mod.generation;
32613098
3262 root_scope.status = .loaded_success;3099 if (queue_linker_work and decl.ty.hasCodeGenBits()) {
3263 keep_tree = true;3100 try mod.comp.bin_file.allocateDeclIndexes(decl);
3101 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl });
32643102
3265 return tree;3103 if (type_changed and mod.emit_h != null) {
3266 },3104 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl });
3105 }
3106 }
32673107
3268 .unloaded_parse_failure => return error.AnalysisFail,3108 if (decl.is_exported) {
3109 const export_src = src; // TODO point to the export token
3110 // The scope needs to have the decl in it.
3111 try mod.analyzeExport(&block_scope.base, export_src, mem.spanZ(decl.name), decl);
3112 }
32693113
3270 .loaded_success => return &root_scope.tree,3114 return type_changed;
3271 }3115 }
3272}3116}
32733117
3274pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {3118/// Returns the depender's index of the dependee.
3275 const tracy = trace(@src());3119pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !void {
3276 defer tracy.end();3120 if (depender == dependee) return;
32773121
3278 // We may be analyzing it for the first time, or this may be3122 log.debug("{*} ({s}) depends on {*} ({s})", .{
3279 // an incremental update. This code handles both cases.3123 depender, depender.name, dependee, dependee.name,
3280 const tree = try mod.getAstTree(container_scope.file_scope);3124 });
3281 const node_tags = tree.nodes.items(.tag);
3282 const node_datas = tree.nodes.items(.data);
3283 const decls = tree.rootDecls();
32843125
3285 try mod.comp.work_queue.ensureUnusedCapacity(decls.len);3126 try depender.dependencies.ensureUnusedCapacity(mod.gpa, 1);
3286 try container_scope.decls.ensureCapacity(mod.gpa, decls.len);3127 try dependee.dependants.ensureUnusedCapacity(mod.gpa, 1);
32873128
3288 // Keep track of the decls that we expect to see in this file so that3129 if (dependee.deletion_flag) {
3289 // we know which ones have been deleted.3130 dependee.deletion_flag = false;
3290 var deleted_decls = std.AutoArrayHashMap(*Decl, void).init(mod.gpa);3131 mod.deletion_set.removeAssertDiscard(dependee);
3291 defer deleted_decls.deinit();
3292 try deleted_decls.ensureCapacity(container_scope.decls.items().len);
3293 for (container_scope.decls.items()) |entry| {
3294 deleted_decls.putAssumeCapacityNoClobber(entry.key, {});
3295 }3132 }
32963133
3297 // Keep track of decls that are invalidated from the update. Ultimately,3134 dependee.dependants.putAssumeCapacity(depender, {});
3298 // the goal is to queue up `analyze_decl` tasks in the work queue for3135 depender.dependencies.putAssumeCapacity(dependee, {});
3299 // the outdated decls, but we cannot queue up the tasks until after3136}
3300 // we find out which ones have been deleted, otherwise there would be
3301 // deleted Decl pointers in the work queue.
3302 var outdated_decls = std.AutoArrayHashMap(*Decl, void).init(mod.gpa);
3303 defer outdated_decls.deinit();
33043137
3305 for (decls) |decl_node| switch (node_tags[decl_node]) {3138pub const ImportFileResult = struct {
3306 .fn_decl => {3139 file: *Scope.File,
3307 const fn_proto = node_datas[decl_node].lhs;3140 is_new: bool,
3308 const body = node_datas[decl_node].rhs;3141};
3309 switch (node_tags[fn_proto]) {
3310 .fn_proto_simple => {
3311 var params: [1]ast.Node.Index = undefined;
3312 try mod.semaContainerFn(
3313 container_scope,
3314 &deleted_decls,
3315 &outdated_decls,
3316 decl_node,
3317 tree.*,
3318 body,
3319 tree.fnProtoSimple(&params, fn_proto),
3320 );
3321 },
3322 .fn_proto_multi => try mod.semaContainerFn(
3323 container_scope,
3324 &deleted_decls,
3325 &outdated_decls,
3326 decl_node,
3327 tree.*,
3328 body,
3329 tree.fnProtoMulti(fn_proto),
3330 ),
3331 .fn_proto_one => {
3332 var params: [1]ast.Node.Index = undefined;
3333 try mod.semaContainerFn(
3334 container_scope,
3335 &deleted_decls,
3336 &outdated_decls,
3337 decl_node,
3338 tree.*,
3339 body,
3340 tree.fnProtoOne(&params, fn_proto),
3341 );
3342 },
3343 .fn_proto => try mod.semaContainerFn(
3344 container_scope,
3345 &deleted_decls,
3346 &outdated_decls,
3347 decl_node,
3348 tree.*,
3349 body,
3350 tree.fnProto(fn_proto),
3351 ),
3352 else => unreachable,
3353 }
3354 },
3355 .fn_proto_simple => {
3356 var params: [1]ast.Node.Index = undefined;
3357 try mod.semaContainerFn(
3358 container_scope,
3359 &deleted_decls,
3360 &outdated_decls,
3361 decl_node,
3362 tree.*,
3363 0,
3364 tree.fnProtoSimple(&params, decl_node),
3365 );
3366 },
3367 .fn_proto_multi => try mod.semaContainerFn(
3368 container_scope,
3369 &deleted_decls,
3370 &outdated_decls,
3371 decl_node,
3372 tree.*,
3373 0,
3374 tree.fnProtoMulti(decl_node),
3375 ),
3376 .fn_proto_one => {
3377 var params: [1]ast.Node.Index = undefined;
3378 try mod.semaContainerFn(
3379 container_scope,
3380 &deleted_decls,
3381 &outdated_decls,
3382 decl_node,
3383 tree.*,
3384 0,
3385 tree.fnProtoOne(&params, decl_node),
3386 );
3387 },
3388 .fn_proto => try mod.semaContainerFn(
3389 container_scope,
3390 &deleted_decls,
3391 &outdated_decls,
3392 decl_node,
3393 tree.*,
3394 0,
3395 tree.fnProto(decl_node),
3396 ),
33973142
3398 .global_var_decl => try mod.semaContainerVar(3143pub fn importPkg(mod: *Module, cur_pkg: *Package, pkg: *Package) !ImportFileResult {
3399 container_scope,3144 const gpa = mod.gpa;
3400 &deleted_decls,
3401 &outdated_decls,
3402 decl_node,
3403 tree.*,
3404 tree.globalVarDecl(decl_node),
3405 ),
3406 .local_var_decl => try mod.semaContainerVar(
3407 container_scope,
3408 &deleted_decls,
3409 &outdated_decls,
3410 decl_node,
3411 tree.*,
3412 tree.localVarDecl(decl_node),
3413 ),
3414 .simple_var_decl => try mod.semaContainerVar(
3415 container_scope,
3416 &deleted_decls,
3417 &outdated_decls,
3418 decl_node,
3419 tree.*,
3420 tree.simpleVarDecl(decl_node),
3421 ),
3422 .aligned_var_decl => try mod.semaContainerVar(
3423 container_scope,
3424 &deleted_decls,
3425 &outdated_decls,
3426 decl_node,
3427 tree.*,
3428 tree.alignedVarDecl(decl_node),
3429 ),
34303145
3431 .@"comptime" => {3146 // The resolved path is used as the key in the import table, to detect if
3432 const name_index = mod.getNextAnonNameIndex();3147 // an import refers to the same as another, despite different relative paths
3433 const name = try std.fmt.allocPrint(mod.gpa, "__comptime_{d}", .{name_index});3148 // or differently mapped package names.
3434 defer mod.gpa.free(name);3149 const resolved_path = try std.fs.path.resolve(gpa, &[_][]const u8{
3150 pkg.root_src_directory.path orelse ".", pkg.root_src_path,
3151 });
3152 var keep_resolved_path = false;
3153 defer if (!keep_resolved_path) gpa.free(resolved_path);
34353154
3436 const name_hash = container_scope.fullyQualifiedNameHash(name);3155 const gop = try mod.import_table.getOrPut(gpa, resolved_path);
3437 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));3156 if (gop.found_existing) return ImportFileResult{
3157 .file = gop.entry.value,
3158 .is_new = false,
3159 };
3160 keep_resolved_path = true; // It's now owned by import_table.
3161
3162 const sub_file_path = try gpa.dupe(u8, pkg.root_src_path);
3163 errdefer gpa.free(sub_file_path);
3164
3165 const new_file = try gpa.create(Scope.File);
3166 errdefer gpa.destroy(new_file);
3167
3168 gop.entry.value = new_file;
3169 new_file.* = .{
3170 .sub_file_path = sub_file_path,
3171 .source = undefined,
3172 .source_loaded = false,
3173 .tree_loaded = false,
3174 .zir_loaded = false,
3175 .stat_size = undefined,
3176 .stat_inode = undefined,
3177 .stat_mtime = undefined,
3178 .tree = undefined,
3179 .zir = undefined,
3180 .status = .never_loaded,
3181 .pkg = pkg,
3182 .root_decl = null,
3183 };
3184 return ImportFileResult{
3185 .file = new_file,
3186 .is_new = true,
3187 };
3188}
34383189
3439 const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash);3190pub fn importFile(
3440 container_scope.decls.putAssumeCapacity(new_decl, {});3191 mod: *Module,
3441 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });3192 cur_file: *Scope.File,
3442 },3193 import_string: []const u8,
3194) !ImportFileResult {
3195 if (cur_file.pkg.table.get(import_string)) |pkg| {
3196 return mod.importPkg(cur_file.pkg, pkg);
3197 }
3198 const gpa = mod.gpa;
34433199
3444 // Container fields are handled in AstGen.3200 // The resolved path is used as the key in the import table, to detect if
3445 .container_field_init,3201 // an import refers to the same as another, despite different relative paths
3446 .container_field_align,3202 // or differently mapped package names.
3447 .container_field,3203 const cur_pkg_dir_path = cur_file.pkg.root_src_directory.path orelse ".";
3448 => continue,3204 const resolved_path = try std.fs.path.resolve(gpa, &[_][]const u8{
3205 cur_pkg_dir_path, cur_file.sub_file_path, "..", import_string,
3206 });
3207 var keep_resolved_path = false;
3208 defer if (!keep_resolved_path) gpa.free(resolved_path);
34493209
3450 .test_decl => {3210 const gop = try mod.import_table.getOrPut(gpa, resolved_path);
3451 if (mod.comp.bin_file.options.is_test) {3211 if (gop.found_existing) return ImportFileResult{
3452 log.err("TODO: analyze test decl", .{});3212 .file = gop.entry.value,
3453 }3213 .is_new = false,
3454 },
3455 .@"usingnamespace" => {
3456 log.err("TODO: analyze usingnamespace decl", .{});
3457 },
3458 else => unreachable,
3459 };3214 };
3460 // Handle explicitly deleted decls from the source code. This is one of two3215 keep_resolved_path = true; // It's now owned by import_table.
3461 // places that Decl deletions happen. The other is in `Compilation`, after3216
3462 // `performAllTheWork`, where we iterate over `Module.deletion_set` and3217 const new_file = try gpa.create(Scope.File);
3463 // delete Decls which are no longer referenced.3218 errdefer gpa.destroy(new_file);
3464 // If a Decl is explicitly deleted from source, and also no longer referenced,3219
3465 // it may be both in this `deleted_decls` set, as well as in the3220 const resolved_root_path = try std.fs.path.resolve(gpa, &[_][]const u8{cur_pkg_dir_path});
3466 // `Module.deletion_set`. To avoid deleting it twice, we remove it from the3221 defer gpa.free(resolved_root_path);
3467 // deletion set at this time.3222
3468 for (deleted_decls.items()) |entry| {3223 if (!mem.startsWith(u8, resolved_path, resolved_root_path)) {
3469 const decl = entry.key;3224 return error.ImportOutsidePkgPath;
3470 log.debug("'{s}' deleted from source", .{decl.name});
3471 if (decl.deletion_flag) {
3472 log.debug("'{s}' redundantly in deletion set; removing", .{decl.name});
3473 mod.deletion_set.removeAssertDiscard(decl);
3474 }
3475 try mod.deleteDecl(decl, &outdated_decls);
3476 }
3477 // Finally we can queue up re-analysis tasks after we have processed
3478 // the deleted decls.
3479 for (outdated_decls.items()) |entry| {
3480 try mod.markOutdatedDecl(entry.key);
3481 }3225 }
3226 // +1 for the directory separator here.
3227 const sub_file_path = try gpa.dupe(u8, resolved_path[resolved_root_path.len + 1 ..]);
3228 errdefer gpa.free(sub_file_path);
3229
3230 log.debug("new importFile. resolved_root_path={s}, resolved_path={s}, sub_file_path={s}, import_string={s}", .{
3231 resolved_root_path, resolved_path, sub_file_path, import_string,
3232 });
3233
3234 gop.entry.value = new_file;
3235 new_file.* = .{
3236 .sub_file_path = sub_file_path,
3237 .source = undefined,
3238 .source_loaded = false,
3239 .tree_loaded = false,
3240 .zir_loaded = false,
3241 .stat_size = undefined,
3242 .stat_inode = undefined,
3243 .stat_mtime = undefined,
3244 .tree = undefined,
3245 .zir = undefined,
3246 .status = .never_loaded,
3247 .pkg = cur_file.pkg,
3248 .root_decl = null,
3249 };
3250 return ImportFileResult{
3251 .file = new_file,
3252 .is_new = true,
3253 };
3482}3254}
34833255
3484fn semaContainerFn(3256pub fn scanNamespace(
3485 mod: *Module,3257 mod: *Module,
3486 container_scope: *Scope.Container,3258 namespace: *Scope.Namespace,
3487 deleted_decls: *std.AutoArrayHashMap(*Decl, void),3259 extra_start: usize,
3488 outdated_decls: *std.AutoArrayHashMap(*Decl, void),3260 decls_len: u32,
3489 decl_node: ast.Node.Index,3261 parent_decl: *Decl,
3490 tree: ast.Tree,3262) InnerError!usize {
3491 body_node: ast.Node.Index,
3492 fn_proto: ast.full.FnProto,
3493) !void {
3494 const tracy = trace(@src());3263 const tracy = trace(@src());
3495 defer tracy.end();3264 defer tracy.end();
34963265
3497 // We will create a Decl for it regardless of analysis status.3266 const gpa = mod.gpa;
3498 const name_token = fn_proto.name_token orelse {3267 const zir = namespace.file_scope.zir;
3499 // This problem will go away with #1717.3268
3500 @panic("TODO missing function name");3269 try mod.comp.work_queue.ensureUnusedCapacity(decls_len);
3270 try namespace.decls.ensureCapacity(gpa, decls_len);
3271
3272 const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable;
3273 var extra_index = extra_start + bit_bags_count;
3274 var bit_bag_index: usize = extra_start;
3275 var cur_bit_bag: u32 = undefined;
3276 var decl_i: u32 = 0;
3277 var scan_decl_iter: ScanDeclIter = .{
3278 .module = mod,
3279 .namespace = namespace,
3280 .parent_decl = parent_decl,
3501 };3281 };
3502 const name = tree.tokenSlice(name_token); // TODO use identifierTokenString3282 while (decl_i < decls_len) : (decl_i += 1) {
3503 const name_hash = container_scope.fullyQualifiedNameHash(name);3283 if (decl_i % 8 == 0) {
3504 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));3284 cur_bit_bag = zir.extra[bit_bag_index];
3505 if (mod.decl_table.get(name_hash)) |decl| {3285 bit_bag_index += 1;
3506 // Update the AST Node index of the decl, even if its contents are unchanged, it may
3507 // have been re-ordered.
3508 const prev_src_node = decl.src_node;
3509 decl.src_node = decl_node;
3510 if (deleted_decls.swapRemove(decl) == null) {
3511 decl.analysis = .sema_failure;
3512 const msg = try ErrorMsg.create(mod.gpa, .{
3513 .container = .{ .file_scope = container_scope.file_scope },
3514 .lazy = .{ .token_abs = name_token },
3515 }, "redefinition of '{s}'", .{decl.name});
3516 errdefer msg.destroy(mod.gpa);
3517 const other_src_loc: SrcLoc = .{
3518 .container = .{ .file_scope = decl.container.file_scope },
3519 .lazy = .{ .node_abs = prev_src_node },
3520 };
3521 try mod.errNoteNonLazy(other_src_loc, msg, "previous definition here", .{});
3522 try mod.failed_decls.putNoClobber(mod.gpa, decl, msg);
3523 } else {
3524 if (!srcHashEql(decl.contents_hash, contents_hash)) {
3525 try outdated_decls.put(decl, {});
3526 decl.contents_hash = contents_hash;
3527 } else switch (mod.comp.bin_file.tag) {
3528 .coff => {
3529 // TODO Implement for COFF
3530 },
3531 .elf => if (decl.fn_link.elf.len != 0) {
3532 // TODO Look into detecting when this would be unnecessary by storing enough state
3533 // in `Decl` to notice that the line number did not change.
3534 mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
3535 },
3536 .macho => if (decl.fn_link.macho.len != 0) {
3537 // TODO Look into detecting when this would be unnecessary by storing enough state
3538 // in `Decl` to notice that the line number did not change.
3539 mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
3540 },
3541 .c, .wasm, .spirv => {},
3542 }
3543 }
3544 } else {
3545 const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash);
3546 container_scope.decls.putAssumeCapacity(new_decl, {});
3547 if (fn_proto.extern_export_token) |maybe_export_token| {
3548 const token_tags = tree.tokens.items(.tag);
3549 if (token_tags[maybe_export_token] == .keyword_export) {
3550 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
3551 }
3552 }3286 }
3553 new_decl.is_pub = fn_proto.visib_token != null;3287 const flags = @truncate(u4, cur_bit_bag);
3288 cur_bit_bag >>= 4;
3289
3290 const decl_sub_index = extra_index;
3291 extra_index += 7; // src_hash(4) + line(1) + name(1) + value(1)
3292 extra_index += @truncate(u1, flags >> 2);
3293 extra_index += @truncate(u1, flags >> 3);
3294
3295 try scanDecl(&scan_decl_iter, decl_sub_index, flags);
3554 }3296 }
3297 return extra_index;
3555}3298}
35563299
3557fn semaContainerVar(3300const ScanDeclIter = struct {
3558 mod: *Module,3301 module: *Module,
3559 container_scope: *Scope.Container,3302 namespace: *Scope.Namespace,
3560 deleted_decls: *std.AutoArrayHashMap(*Decl, void),3303 parent_decl: *Decl,
3561 outdated_decls: *std.AutoArrayHashMap(*Decl, void),3304 usingnamespace_index: usize = 0,
3562 decl_node: ast.Node.Index,3305 comptime_index: usize = 0,
3563 tree: ast.Tree,3306 unnamed_test_index: usize = 0,
3564 var_decl: ast.full.VarDecl,3307};
3565) !void {3308
3309fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!void {
3566 const tracy = trace(@src());3310 const tracy = trace(@src());
3567 defer tracy.end();3311 defer tracy.end();
35683312
3569 const name_token = var_decl.ast.mut_token + 1;3313 const mod = iter.module;
3570 const name = tree.tokenSlice(name_token); // TODO identifierTokenString3314 const namespace = iter.namespace;
3571 const name_hash = container_scope.fullyQualifiedNameHash(name);3315 const gpa = mod.gpa;
3572 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));3316 const zir = namespace.file_scope.zir;
3573 if (mod.decl_table.get(name_hash)) |decl| {3317
3574 // Update the AST Node index of the decl, even if its contents are unchanged, it may3318 // zig fmt: off
3575 // have been re-ordered.3319 const is_pub = (flags & 0b0001) != 0;
3576 const prev_src_node = decl.src_node;3320 const is_exported = (flags & 0b0010) != 0;
3577 decl.src_node = decl_node;3321 const has_align = (flags & 0b0100) != 0;
3578 if (deleted_decls.swapRemove(decl) == null) {3322 const has_linksection = (flags & 0b1000) != 0;
3579 decl.analysis = .sema_failure;3323 // zig fmt: on
3580 const msg = try ErrorMsg.create(mod.gpa, .{3324
3581 .container = .{ .file_scope = container_scope.file_scope },3325 const line = iter.parent_decl.relativeToLine(zir.extra[decl_sub_index + 4]);
3582 .lazy = .{ .token_abs = name_token },3326 const decl_name_index = zir.extra[decl_sub_index + 5];
3583 }, "redefinition of '{s}'", .{decl.name});3327 const decl_index = zir.extra[decl_sub_index + 6];
3584 errdefer msg.destroy(mod.gpa);3328 const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node;
3585 const other_src_loc: SrcLoc = .{3329 const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);
3586 .container = .{ .file_scope = decl.container.file_scope },3330
3587 .lazy = .{ .node_abs = prev_src_node },3331 // Every Decl needs a name.
3588 };3332 var is_named_test = false;
3589 try mod.errNoteNonLazy(other_src_loc, msg, "previous definition here", .{});3333 const decl_name: [:0]const u8 = switch (decl_name_index) {
3590 try mod.failed_decls.putNoClobber(mod.gpa, decl, msg);3334 0 => name: {
3591 } else if (!srcHashEql(decl.contents_hash, contents_hash)) {3335 if (is_exported) {
3592 try outdated_decls.put(decl, {});3336 const i = iter.usingnamespace_index;
3593 decl.contents_hash = contents_hash;3337 iter.usingnamespace_index += 1;
3594 }3338 break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i});
3595 } else {3339 } else {
3596 const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash);3340 const i = iter.comptime_index;
3597 container_scope.decls.putAssumeCapacity(new_decl, {});3341 iter.comptime_index += 1;
3598 if (var_decl.extern_export_token) |maybe_export_token| {3342 break :name try std.fmt.allocPrintZ(gpa, "comptime_{d}", .{i});
3599 const token_tags = tree.tokens.items(.tag);3343 }
3600 if (token_tags[maybe_export_token] == .keyword_export) {3344 },
3601 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });3345 1 => name: {
3346 const i = iter.unnamed_test_index;
3347 iter.unnamed_test_index += 1;
3348 break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i});
3349 },
3350 else => name: {
3351 const raw_name = zir.nullTerminatedString(decl_name_index);
3352 if (raw_name.len == 0) {
3353 is_named_test = true;
3354 const test_name = zir.nullTerminatedString(decl_name_index + 1);
3355 break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name});
3356 } else {
3357 break :name try gpa.dupeZ(u8, raw_name);
3602 }3358 }
3359 },
3360 };
3361
3362 // We create a Decl for it regardless of analysis status.
3363 const gop = try namespace.decls.getOrPut(gpa, decl_name);
3364 if (!gop.found_existing) {
3365 const new_decl = try mod.allocateNewDecl(namespace, decl_node);
3366 log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace });
3367 new_decl.src_line = line;
3368 new_decl.name = decl_name;
3369 gop.entry.value = new_decl;
3370 // Exported decls, comptime decls, usingnamespace decls, and
3371 // test decls if in test mode, get analyzed.
3372 const want_analysis = is_exported or switch (decl_name_index) {
3373 0 => true, // comptime decl
3374 1 => mod.comp.bin_file.options.is_test, // test decl
3375 else => is_named_test and mod.comp.bin_file.options.is_test,
3376 };
3377 if (want_analysis) {
3378 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
3379 }
3380 new_decl.is_pub = is_pub;
3381 new_decl.is_exported = is_exported;
3382 new_decl.has_align = has_align;
3383 new_decl.has_linksection = has_linksection;
3384 new_decl.zir_decl_index = @intCast(u32, decl_sub_index);
3385 return;
3386 }
3387 gpa.free(decl_name);
3388 const decl = gop.entry.value;
3389 log.debug("scan existing {*} ({s}) of {*}", .{ decl, decl.name, namespace });
3390 // Update the AST node of the decl; even if its contents are unchanged, it may
3391 // have been re-ordered.
3392 const prev_src_node = decl.src_node;
3393 decl.src_node = decl_node;
3394 decl.src_line = line;
3395
3396 decl.is_pub = is_pub;
3397 decl.is_exported = is_exported;
3398 decl.has_align = has_align;
3399 decl.has_linksection = has_linksection;
3400 decl.zir_decl_index = @intCast(u32, decl_sub_index);
3401 if (decl.getFunction()) |func| {
3402 switch (mod.comp.bin_file.tag) {
3403 .coff => {
3404 // TODO Implement for COFF
3405 },
3406 .elf => if (decl.fn_link.elf.len != 0) {
3407 // TODO Look into detecting when this would be unnecessary by storing enough state
3408 // in `Decl` to notice that the line number did not change.
3409 mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
3410 },
3411 .macho => if (decl.fn_link.macho.len != 0) {
3412 // TODO Look into detecting when this would be unnecessary by storing enough state
3413 // in `Decl` to notice that the line number did not change.
3414 mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
3415 },
3416 .c, .wasm, .spirv => {},
3603 }3417 }
3604 new_decl.is_pub = var_decl.visib_token != null;
3605 }3418 }
3606}3419}
36073420
3608pub fn deleteDecl(3421/// Make it as if the semantic analysis for this Decl never happened.
3422pub fn clearDecl(
3609 mod: *Module,3423 mod: *Module,
3610 decl: *Decl,3424 decl: *Decl,
3611 outdated_decls: ?*std.AutoArrayHashMap(*Decl, void),3425 outdated_decls: ?*std.AutoArrayHashMap(*Decl, void),
3612) !void {3426) Allocator.Error!void {
3613 const tracy = trace(@src());3427 const tracy = trace(@src());
3614 defer tracy.end();3428 defer tracy.end();
36153429
3616 log.debug("deleting decl '{s}'", .{decl.name});3430 log.debug("clearing {*} ({s})", .{ decl, decl.name });
3431
3432 const gpa = mod.gpa;
3433 try mod.deletion_set.ensureUnusedCapacity(gpa, decl.dependencies.count());
36173434
3618 if (outdated_decls) |map| {3435 if (outdated_decls) |map| {
3619 _ = map.swapRemove(decl);3436 _ = map.swapRemove(decl);
3620 try map.ensureCapacity(map.count() + decl.dependants.count());3437 try map.ensureUnusedCapacity(decl.dependants.count());
3621 }3438 }
3622 try mod.deletion_set.ensureCapacity(mod.gpa, mod.deletion_set.count() +
3623 decl.dependencies.count());
3624
3625 // Remove from the namespace it resides in. In the case of an anonymous Decl it will
3626 // not be present in the set, and this does nothing.
3627 decl.container.removeDecl(decl);
36283439
3629 const name_hash = decl.fullyQualifiedNameHash();3440 // Remove itself from its dependencies.
3630 mod.decl_table.removeAssertDiscard(name_hash);
3631 // Remove itself from its dependencies, because we are about to destroy the decl pointer.
3632 for (decl.dependencies.items()) |entry| {3441 for (decl.dependencies.items()) |entry| {
3633 const dep = entry.key;3442 const dep = entry.key;
3634 dep.removeDependant(decl);3443 dep.removeDependant(decl);
...@@ -3639,6 +3448,8 @@ pub fn deleteDecl(...@@ -3639,6 +3448,8 @@ pub fn deleteDecl(
3639 mod.deletion_set.putAssumeCapacity(dep, {});3448 mod.deletion_set.putAssumeCapacity(dep, {});
3640 }3449 }
3641 }3450 }
3451 decl.dependencies.clearRetainingCapacity();
3452
3642 // Anything that depends on this deleted decl needs to be re-analyzed.3453 // Anything that depends on this deleted decl needs to be re-analyzed.
3643 for (decl.dependants.items()) |entry| {3454 for (decl.dependants.items()) |entry| {
3644 const dep = entry.key;3455 const dep = entry.key;
...@@ -3654,17 +3465,55 @@ pub fn deleteDecl(...@@ -3654,17 +3465,55 @@ pub fn deleteDecl(
3654 assert(mod.deletion_set.contains(dep));3465 assert(mod.deletion_set.contains(dep));
3655 }3466 }
3656 }3467 }
3468 decl.dependants.clearRetainingCapacity();
3469
3657 if (mod.failed_decls.swapRemove(decl)) |entry| {3470 if (mod.failed_decls.swapRemove(decl)) |entry| {
3658 entry.value.destroy(mod.gpa);3471 entry.value.destroy(gpa);
3472 }
3473 if (mod.emit_h) |emit_h| {
3474 if (emit_h.failed_decls.swapRemove(decl)) |entry| {
3475 entry.value.destroy(gpa);
3476 }
3477 emit_h.decl_table.removeAssertDiscard(decl);
3478 }
3479 _ = mod.compile_log_decls.swapRemove(decl);
3480 mod.deleteDeclExports(decl);
3481
3482 if (decl.has_tv) {
3483 if (decl.ty.hasCodeGenBits()) {
3484 mod.comp.bin_file.freeDecl(decl);
3485
3486 // TODO instead of a union, put this memory trailing Decl objects,
3487 // and allow it to be variably sized.
3488 decl.link = switch (mod.comp.bin_file.tag) {
3489 .coff => .{ .coff = link.File.Coff.TextBlock.empty },
3490 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
3491 .macho => .{ .macho = link.File.MachO.TextBlock.empty },
3492 .c => .{ .c = link.File.C.DeclBlock.empty },
3493 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
3494 .spirv => .{ .spirv = {} },
3495 };
3496 decl.fn_link = switch (mod.comp.bin_file.tag) {
3497 .coff => .{ .coff = {} },
3498 .elf => .{ .elf = link.File.Elf.SrcFn.empty },
3499 .macho => .{ .macho = link.File.MachO.SrcFn.empty },
3500 .c => .{ .c = link.File.C.FnBlock.empty },
3501 .wasm => .{ .wasm = link.File.Wasm.FnData.empty },
3502 .spirv => .{ .spirv = .{} },
3503 };
3504 }
3505 if (decl.getInnerNamespace()) |namespace| {
3506 try namespace.deleteAllDecls(mod, outdated_decls);
3507 }
3508 decl.clearValues(gpa);
3659 }3509 }
3660 if (mod.emit_h_failed_decls.swapRemove(decl)) |entry| {3510
3661 entry.value.destroy(mod.gpa);3511 if (decl.deletion_flag) {
3512 decl.deletion_flag = false;
3513 mod.deletion_set.swapRemoveAssertDiscard(decl);
3662 }3514 }
3663 _ = mod.compile_log_decls.swapRemove(decl);
3664 mod.deleteDeclExports(decl);
3665 mod.comp.bin_file.freeDecl(decl);
36663515
3667 decl.destroy(mod);3516 decl.analysis = .unreferenced;
3668}3517}
36693518
3670/// Delete all the Export objects that are caused by this Decl. Re-analysis of3519/// Delete all the Export objects that are caused by this Decl. Re-analysis of
...@@ -3700,7 +3549,6 @@ fn deleteDeclExports(mod: *Module, decl: *Decl) void {...@@ -3700,7 +3549,6 @@ fn deleteDeclExports(mod: *Module, decl: *Decl) void {
3700 if (mod.failed_exports.swapRemove(exp)) |entry| {3549 if (mod.failed_exports.swapRemove(exp)) |entry| {
3701 entry.value.destroy(mod.gpa);3550 entry.value.destroy(mod.gpa);
3702 }3551 }
3703 _ = mod.symbol_exports.swapRemove(exp.options.name);
3704 mod.gpa.free(exp.options.name);3552 mod.gpa.free(exp.options.name);
3705 mod.gpa.destroy(exp);3553 mod.gpa.destroy(exp);
3706 }3554 }
...@@ -3712,16 +3560,15 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {...@@ -3712,16 +3560,15 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {
3712 defer tracy.end();3560 defer tracy.end();
37133561
3714 // Use the Decl's arena for function memory.3562 // Use the Decl's arena for function memory.
3715 var arena = decl.typed_value.most_recent.arena.?.promote(mod.gpa);3563 var arena = decl.value_arena.?.promote(mod.gpa);
3716 defer decl.typed_value.most_recent.arena.?.* = arena.state;3564 defer decl.value_arena.?.* = arena.state;
37173565
3718 const fn_ty = decl.typed_value.most_recent.typed_value.ty;3566 const fn_ty = decl.ty;
3719 const param_inst_list = try mod.gpa.alloc(*ir.Inst, fn_ty.fnParamLen());3567 const param_inst_list = try mod.gpa.alloc(*ir.Inst, fn_ty.fnParamLen());
3720 defer mod.gpa.free(param_inst_list);3568 defer mod.gpa.free(param_inst_list);
37213569
3722 for (param_inst_list) |*param_inst, param_index| {3570 for (param_inst_list) |*param_inst, param_index| {
3723 const param_type = fn_ty.fnParamType(param_index);3571 const param_type = fn_ty.fnParamType(param_index);
3724 const name = func.zir.nullTerminatedString(func.zir.extra[param_index]);
3725 const arg_inst = try arena.allocator.create(ir.Inst.Arg);3572 const arg_inst = try arena.allocator.create(ir.Inst.Arg);
3726 arg_inst.* = .{3573 arg_inst.* = .{
3727 .base = .{3574 .base = .{
...@@ -3729,23 +3576,25 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {...@@ -3729,23 +3576,25 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {
3729 .ty = param_type,3576 .ty = param_type,
3730 .src = .unneeded,3577 .src = .unneeded,
3731 },3578 },
3732 .name = name,3579 .name = undefined, // Set in the semantic analysis of the arg instruction.
3733 };3580 };
3734 param_inst.* = &arg_inst.base;3581 param_inst.* = &arg_inst.base;
3735 }3582 }
37363583
3584 const zir = decl.namespace.file_scope.zir;
3585
3737 var sema: Sema = .{3586 var sema: Sema = .{
3738 .mod = mod,3587 .mod = mod,
3739 .gpa = mod.gpa,3588 .gpa = mod.gpa,
3740 .arena = &arena.allocator,3589 .arena = &arena.allocator,
3741 .code = func.zir,3590 .code = zir,
3742 .inst_map = try mod.gpa.alloc(*ir.Inst, func.zir.instructions.len),
3743 .owner_decl = decl,3591 .owner_decl = decl,
3592 .namespace = decl.namespace,
3744 .func = func,3593 .func = func,
3745 .owner_func = func,3594 .owner_func = func,
3746 .param_inst_list = param_inst_list,3595 .param_inst_list = param_inst_list,
3747 };3596 };
3748 defer mod.gpa.free(sema.inst_map);3597 defer sema.deinit();
37493598
3750 var inner_block: Scope.Block = .{3599 var inner_block: Scope.Block = .{
3751 .parent = null,3600 .parent = null,
...@@ -3757,13 +3606,13 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {...@@ -3757,13 +3606,13 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {
3757 };3606 };
3758 defer inner_block.instructions.deinit(mod.gpa);3607 defer inner_block.instructions.deinit(mod.gpa);
37593608
3760 // TZIR currently requires the arg parameters to be the first N instructions3609 // AIR currently requires the arg parameters to be the first N instructions
3761 try inner_block.instructions.appendSlice(mod.gpa, param_inst_list);3610 try inner_block.instructions.appendSlice(mod.gpa, param_inst_list);
37623611
3763 func.state = .in_progress;3612 func.state = .in_progress;
3764 log.debug("set {s} to in_progress", .{decl.name});3613 log.debug("set {s} to in_progress", .{decl.name});
37653614
3766 _ = try sema.root(&inner_block);3615 try sema.analyzeFnBody(&inner_block, func.zir_body_inst);
37673616
3768 const instructions = try arena.allocator.dupe(*ir.Inst, inner_block.instructions.items);3617 const instructions = try arena.allocator.dupe(*ir.Inst, inner_block.instructions.items);
3769 func.state = .success;3618 func.state = .success;
...@@ -3772,24 +3621,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {...@@ -3772,24 +3621,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {
3772}3621}
37733622
3774fn markOutdatedDecl(mod: *Module, decl: *Decl) !void {3623fn markOutdatedDecl(mod: *Module, decl: *Decl) !void {
3775 log.debug("mark {s} outdated", .{decl.name});3624 log.debug("mark outdated {*} ({s})", .{ decl, decl.name });
3776 try mod.comp.work_queue.writeItem(.{ .analyze_decl = decl });3625 try mod.comp.work_queue.writeItem(.{ .analyze_decl = decl });
3777 if (mod.failed_decls.swapRemove(decl)) |entry| {3626 if (mod.failed_decls.swapRemove(decl)) |entry| {
3778 entry.value.destroy(mod.gpa);3627 entry.value.destroy(mod.gpa);
3779 }3628 }
3780 if (mod.emit_h_failed_decls.swapRemove(decl)) |entry| {3629 if (mod.emit_h) |emit_h| {
3781 entry.value.destroy(mod.gpa);3630 if (emit_h.failed_decls.swapRemove(decl)) |entry| {
3631 entry.value.destroy(mod.gpa);
3632 }
3782 }3633 }
3783 _ = mod.compile_log_decls.swapRemove(decl);3634 _ = mod.compile_log_decls.swapRemove(decl);
3784 decl.analysis = .outdated;3635 decl.analysis = .outdated;
3785}3636}
37863637
3787fn allocateNewDecl(3638fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node.Index) !*Decl {
3788 mod: *Module,
3789 scope: *Scope,
3790 src_node: ast.Node.Index,
3791 contents_hash: std.zig.SrcHash,
3792) !*Decl {
3793 // If we have emit-h then we must allocate a bigger structure to store the emit-h state.3639 // If we have emit-h then we must allocate a bigger structure to store the emit-h state.
3794 const new_decl: *Decl = if (mod.emit_h != null) blk: {3640 const new_decl: *Decl = if (mod.emit_h != null) blk: {
3795 const parent_struct = try mod.gpa.create(DeclPlusEmitH);3641 const parent_struct = try mod.gpa.create(DeclPlusEmitH);
...@@ -3802,12 +3648,18 @@ fn allocateNewDecl(...@@ -3802,12 +3648,18 @@ fn allocateNewDecl(
38023648
3803 new_decl.* = .{3649 new_decl.* = .{
3804 .name = "",3650 .name = "",
3805 .container = scope.namespace(),3651 .namespace = namespace,
3806 .src_node = src_node,3652 .src_node = src_node,
3807 .typed_value = .{ .never_succeeded = {} },3653 .src_line = undefined,
3654 .has_tv = false,
3655 .owns_tv = false,
3656 .ty = undefined,
3657 .val = undefined,
3658 .align_val = undefined,
3659 .linksection_val = undefined,
3808 .analysis = .unreferenced,3660 .analysis = .unreferenced,
3809 .deletion_flag = false,3661 .deletion_flag = false,
3810 .contents_hash = contents_hash,3662 .zir_decl_index = 0,
3811 .link = switch (mod.comp.bin_file.tag) {3663 .link = switch (mod.comp.bin_file.tag) {
3812 .coff => .{ .coff = link.File.Coff.TextBlock.empty },3664 .coff => .{ .coff = link.File.Coff.TextBlock.empty },
3813 .elf => .{ .elf = link.File.Elf.TextBlock.empty },3665 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
...@@ -3826,26 +3678,13 @@ fn allocateNewDecl(...@@ -3826,26 +3678,13 @@ fn allocateNewDecl(
3826 },3678 },
3827 .generation = 0,3679 .generation = 0,
3828 .is_pub = false,3680 .is_pub = false,
3681 .is_exported = false,
3682 .has_linksection = false,
3683 .has_align = false,
3829 };3684 };
3830 return new_decl;3685 return new_decl;
3831}3686}
38323687
3833fn createNewDecl(
3834 mod: *Module,
3835 scope: *Scope,
3836 decl_name: []const u8,
3837 src_node: ast.Node.Index,
3838 name_hash: Scope.NameHash,
3839 contents_hash: std.zig.SrcHash,
3840) !*Decl {
3841 try mod.decl_table.ensureCapacity(mod.gpa, mod.decl_table.items().len + 1);
3842 const new_decl = try mod.allocateNewDecl(scope, src_node, contents_hash);
3843 errdefer mod.gpa.destroy(new_decl);
3844 new_decl.name = try mem.dupeZ(mod.gpa, u8, decl_name);
3845 mod.decl_table.putAssumeCapacityNoClobber(name_hash, new_decl);
3846 return new_decl;
3847}
3848
3849/// Get error value for error tag `name`.3688/// Get error value for error tag `name`.
3850pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(ErrorInt).Entry {3689pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(ErrorInt).Entry {
3851 const gop = try mod.global_error_set.getOrPut(mod.gpa, name);3690 const gop = try mod.global_error_set.getOrPut(mod.gpa, name);
...@@ -3868,10 +3707,9 @@ pub fn analyzeExport(...@@ -3868,10 +3707,9 @@ pub fn analyzeExport(
3868 exported_decl: *Decl,3707 exported_decl: *Decl,
3869) !void {3708) !void {
3870 try mod.ensureDeclAnalyzed(exported_decl);3709 try mod.ensureDeclAnalyzed(exported_decl);
3871 const typed_value = exported_decl.typed_value.most_recent.typed_value;3710 switch (exported_decl.ty.zigTypeTag()) {
3872 switch (typed_value.ty.zigTypeTag()) {
3873 .Fn => {},3711 .Fn => {},
3874 else => return mod.fail(scope, src, "unable to export type '{}'", .{typed_value.ty}),3712 else => return mod.fail(scope, src, "unable to export type '{}'", .{exported_decl.ty}),
3875 }3713 }
38763714
3877 try mod.decl_exports.ensureCapacity(mod.gpa, mod.decl_exports.items().len + 1);3715 try mod.decl_exports.ensureCapacity(mod.gpa, mod.decl_exports.items().len + 1);
...@@ -3885,6 +3723,10 @@ pub fn analyzeExport(...@@ -3885,6 +3723,10 @@ pub fn analyzeExport(
38853723
3886 const owner_decl = scope.ownerDecl().?;3724 const owner_decl = scope.ownerDecl().?;
38873725
3726 log.debug("exporting Decl '{s}' as symbol '{s}' from Decl '{s}'", .{
3727 exported_decl.name, borrowed_symbol_name, owner_decl.name,
3728 });
3729
3888 new_export.* = .{3730 new_export.* = .{
3889 .options = .{ .name = symbol_name },3731 .options = .{ .name = symbol_name },
3890 .src = src,3732 .src = src,
...@@ -3918,39 +3760,6 @@ pub fn analyzeExport(...@@ -3918,39 +3760,6 @@ pub fn analyzeExport(
3918 de_gop.entry.value = try mod.gpa.realloc(de_gop.entry.value, de_gop.entry.value.len + 1);3760 de_gop.entry.value = try mod.gpa.realloc(de_gop.entry.value, de_gop.entry.value.len + 1);
3919 de_gop.entry.value[de_gop.entry.value.len - 1] = new_export;3761 de_gop.entry.value[de_gop.entry.value.len - 1] = new_export;
3920 errdefer de_gop.entry.value = mod.gpa.shrink(de_gop.entry.value, de_gop.entry.value.len - 1);3762 errdefer de_gop.entry.value = mod.gpa.shrink(de_gop.entry.value, de_gop.entry.value.len - 1);
3921
3922 if (mod.symbol_exports.get(symbol_name)) |other_export| {
3923 new_export.status = .failed_retryable;
3924 try mod.failed_exports.ensureCapacity(mod.gpa, mod.failed_exports.items().len + 1);
3925 const msg = try mod.errMsg(
3926 scope,
3927 src,
3928 "exported symbol collision: {s}",
3929 .{symbol_name},
3930 );
3931 errdefer msg.destroy(mod.gpa);
3932 try mod.errNote(
3933 &other_export.owner_decl.container.base,
3934 other_export.src,
3935 msg,
3936 "other symbol here",
3937 .{},
3938 );
3939 mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
3940 new_export.status = .failed;
3941 return;
3942 }
3943
3944 try mod.symbol_exports.putNoClobber(mod.gpa, symbol_name, new_export);
3945 mod.comp.bin_file.updateDeclExports(mod, exported_decl, de_gop.entry.value) catch |err| switch (err) {
3946 error.OutOfMemory => return error.OutOfMemory,
3947 else => {
3948 new_export.status = .failed_retryable;
3949 try mod.failed_exports.ensureCapacity(mod.gpa, mod.failed_exports.items().len + 1);
3950 const msg = try mod.errMsg(scope, src, "unable to export: {s}", .{@errorName(err)});
3951 mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
3952 },
3953 };
3954}3763}
3955pub fn constInst(mod: *Module, arena: *Allocator, src: LazySrcLoc, typed_value: TypedValue) !*ir.Inst {3764pub fn constInst(mod: *Module, arena: *Allocator, src: LazySrcLoc, typed_value: TypedValue) !*ir.Inst {
3956 const const_inst = try arena.create(ir.Inst.Constant);3765 const const_inst = try arena.create(ir.Inst.Constant);
...@@ -4040,31 +3849,38 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b...@@ -4040,31 +3849,38 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b
4040 }3849 }
4041}3850}
40423851
4043pub fn createAnonymousDecl(3852pub fn deleteAnonDecl(mod: *Module, scope: *Scope, decl: *Decl) void {
3853 const scope_decl = scope.ownerDecl().?;
3854 scope_decl.namespace.anon_decls.swapRemoveAssertDiscard(decl);
3855 decl.destroy(mod);
3856}
3857
3858/// Takes ownership of `name` even if it returns an error.
3859pub fn createAnonymousDeclNamed(
4044 mod: *Module,3860 mod: *Module,
4045 scope: *Scope,3861 scope: *Scope,
4046 decl_arena: *std.heap.ArenaAllocator,
4047 typed_value: TypedValue,3862 typed_value: TypedValue,
3863 name: [:0]u8,
4048) !*Decl {3864) !*Decl {
4049 const name_index = mod.getNextAnonNameIndex();3865 errdefer mod.gpa.free(name);
3866
4050 const scope_decl = scope.ownerDecl().?;3867 const scope_decl = scope.ownerDecl().?;
4051 const name = try std.fmt.allocPrint(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index });3868 const namespace = scope_decl.namespace;
4052 defer mod.gpa.free(name);3869 try namespace.anon_decls.ensureUnusedCapacity(mod.gpa, 1);
4053 const name_hash = scope.namespace().fullyQualifiedNameHash(name);
4054 const src_hash: std.zig.SrcHash = undefined;
4055 const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_node, name_hash, src_hash);
4056 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
40573870
4058 decl_arena_state.* = decl_arena.state;3871 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
4059 new_decl.typed_value = .{3872
4060 .most_recent = .{3873 new_decl.name = name;
4061 .typed_value = typed_value,3874 new_decl.src_line = scope_decl.src_line;
4062 .arena = decl_arena_state,3875 new_decl.ty = typed_value.ty;
4063 },3876 new_decl.val = typed_value.val;
4064 };3877 new_decl.has_tv = true;
3878 new_decl.owns_tv = true;
4065 new_decl.analysis = .complete;3879 new_decl.analysis = .complete;
4066 new_decl.generation = mod.generation;3880 new_decl.generation = mod.generation;
40673881
3882 namespace.anon_decls.putAssumeCapacityNoClobber(new_decl, {});
3883
4068 // TODO: This generates the Decl into the machine code file if it is of a3884 // TODO: This generates the Decl into the machine code file if it is of a
4069 // type that is non-zero size. We should be able to further improve the3885 // type that is non-zero size. We should be able to further improve the
4070 // compiler to omit Decls which are only referenced at compile-time and not runtime.3886 // compiler to omit Decls which are only referenced at compile-time and not runtime.
...@@ -4076,59 +3892,19 @@ pub fn createAnonymousDecl(...@@ -4076,59 +3892,19 @@ pub fn createAnonymousDecl(
4076 return new_decl;3892 return new_decl;
4077}3893}
40783894
4079pub fn createContainerDecl(3895pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl {
4080 mod: *Module,
4081 scope: *Scope,
4082 base_token: std.zig.ast.TokenIndex,
4083 decl_arena: *std.heap.ArenaAllocator,
4084 typed_value: TypedValue,
4085) !*Decl {
4086 const scope_decl = scope.ownerDecl().?;3896 const scope_decl = scope.ownerDecl().?;
4087 const name = try mod.getAnonTypeName(scope, base_token);3897 const name_index = mod.getNextAnonNameIndex();
4088 defer mod.gpa.free(name);3898 const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{
4089 const name_hash = scope.namespace().fullyQualifiedNameHash(name);3899 scope_decl.name, name_index,
4090 const src_hash: std.zig.SrcHash = undefined;3900 });
4091 const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_node, name_hash, src_hash);3901 return mod.createAnonymousDeclNamed(scope, typed_value, name);
4092 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
4093
4094 decl_arena_state.* = decl_arena.state;
4095 new_decl.typed_value = .{
4096 .most_recent = .{
4097 .typed_value = typed_value,
4098 .arena = decl_arena_state,
4099 },
4100 };
4101 new_decl.analysis = .complete;
4102 new_decl.generation = mod.generation;
4103
4104 return new_decl;
4105}
4106
4107fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenIndex) ![]u8 {
4108 // TODO add namespaces, generic function signatrues
4109 const tree = scope.tree();
4110 const token_tags = tree.tokens.items(.tag);
4111 const base_name = switch (token_tags[base_token]) {
4112 .keyword_struct => "struct",
4113 .keyword_enum => "enum",
4114 .keyword_union => "union",
4115 .keyword_opaque => "opaque",
4116 else => unreachable,
4117 };
4118 const loc = tree.tokenLocation(0, base_token);
4119 return std.fmt.allocPrint(mod.gpa, "{s}:{d}:{d}", .{ base_name, loc.line, loc.column });
4120}3902}
41213903
4122fn getNextAnonNameIndex(mod: *Module) usize {3904pub fn getNextAnonNameIndex(mod: *Module) usize {
4123 return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic);3905 return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic);
4124}3906}
41253907
4126pub fn lookupDeclName(mod: *Module, scope: *Scope, ident_name: []const u8) ?*Decl {
4127 const namespace = scope.namespace();
4128 const name_hash = namespace.fullyQualifiedNameHash(ident_name);
4129 return mod.decl_table.get(name_hash);
4130}
4131
4132pub fn makeIntType(arena: *Allocator, signedness: std.builtin.Signedness, bits: u16) !Type {3908pub fn makeIntType(arena: *Allocator, signedness: std.builtin.Signedness, bits: u16) !Type {
4133 const int_payload = try arena.create(Type.Payload.Bits);3909 const int_payload = try arena.create(Type.Payload.Bits);
4134 int_payload.* = .{3910 int_payload.* = .{
...@@ -4194,20 +3970,6 @@ pub fn fail(...@@ -4194,20 +3970,6 @@ pub fn fail(
4194 return mod.failWithOwnedErrorMsg(scope, err_msg);3970 return mod.failWithOwnedErrorMsg(scope, err_msg);
4195}3971}
41963972
4197/// Same as `fail`, except given an absolute byte offset, and the function sets up the `LazySrcLoc`
4198/// for pointing at it relatively by subtracting from the containing `Decl`.
4199pub fn failOff(
4200 mod: *Module,
4201 scope: *Scope,
4202 byte_offset: u32,
4203 comptime format: []const u8,
4204 args: anytype,
4205) InnerError {
4206 const decl_byte_offset = scope.srcDecl().?.srcByteOffset();
4207 const src: LazySrcLoc = .{ .byte_offset = byte_offset - decl_byte_offset };
4208 return mod.fail(scope, src, format, args);
4209}
4210
4211/// Same as `fail`, except given a token index, and the function sets up the `LazySrcLoc`3973/// Same as `fail`, except given a token index, and the function sets up the `LazySrcLoc`
4212/// for pointing at it relatively by subtracting from the containing `Decl`.3974/// for pointing at it relatively by subtracting from the containing `Decl`.
4213pub fn failTok(3975pub fn failTok(
...@@ -4236,6 +3998,7 @@ pub fn failNode(...@@ -4236,6 +3998,7 @@ pub fn failNode(
42363998
4237pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) InnerError {3999pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) InnerError {
4238 @setCold(true);4000 @setCold(true);
4001
4239 {4002 {
4240 errdefer err_msg.destroy(mod.gpa);4003 errdefer err_msg.destroy(mod.gpa);
4241 try mod.failed_decls.ensureCapacity(mod.gpa, mod.failed_decls.items().len + 1);4004 try mod.failed_decls.ensureCapacity(mod.gpa, mod.failed_decls.items().len + 1);
...@@ -4252,40 +4015,12 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) In...@@ -4252,40 +4015,12 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) In
4252 }4015 }
4253 mod.failed_decls.putAssumeCapacityNoClobber(block.sema.owner_decl, err_msg);4016 mod.failed_decls.putAssumeCapacityNoClobber(block.sema.owner_decl, err_msg);
4254 },4017 },
4255 .gen_zir => {
4256 const gen_zir = scope.cast(Scope.GenZir).?;
4257 gen_zir.astgen.decl.analysis = .sema_failure;
4258 gen_zir.astgen.decl.generation = mod.generation;
4259 mod.failed_decls.putAssumeCapacityNoClobber(gen_zir.astgen.decl, err_msg);
4260 },
4261 .local_val => {
4262 const gen_zir = scope.cast(Scope.LocalVal).?.gen_zir;
4263 gen_zir.astgen.decl.analysis = .sema_failure;
4264 gen_zir.astgen.decl.generation = mod.generation;
4265 mod.failed_decls.putAssumeCapacityNoClobber(gen_zir.astgen.decl, err_msg);
4266 },
4267 .local_ptr => {
4268 const gen_zir = scope.cast(Scope.LocalPtr).?.gen_zir;
4269 gen_zir.astgen.decl.analysis = .sema_failure;
4270 gen_zir.astgen.decl.generation = mod.generation;
4271 mod.failed_decls.putAssumeCapacityNoClobber(gen_zir.astgen.decl, err_msg);
4272 },
4273 .file => unreachable,4018 .file => unreachable,
4274 .container => unreachable,4019 .namespace => unreachable,
4275 .decl_ref => {
4276 const decl_ref = scope.cast(Scope.DeclRef).?;
4277 decl_ref.decl.analysis = .sema_failure;
4278 decl_ref.decl.generation = mod.generation;
4279 mod.failed_decls.putAssumeCapacityNoClobber(decl_ref.decl, err_msg);
4280 },
4281 }4020 }
4282 return error.AnalysisFail;4021 return error.AnalysisFail;
4283}4022}
42844023
4285fn srcHashEql(a: std.zig.SrcHash, b: std.zig.SrcHash) bool {
4286 return @bitCast(u128, a) == @bitCast(u128, b);
4287}
4288
4289pub fn intAdd(allocator: *Allocator, lhs: Value, rhs: Value) !Value {4024pub fn intAdd(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
4290 // TODO is this a performance issue? maybe we should try the operation without4025 // TODO is this a performance issue? maybe we should try the operation without
4291 // resorting to BigInt first.4026 // resorting to BigInt first.
...@@ -4330,6 +4065,37 @@ pub fn intSub(allocator: *Allocator, lhs: Value, rhs: Value) !Value {...@@ -4330,6 +4065,37 @@ pub fn intSub(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
4330 }4065 }
4331}4066}
43324067
4068pub fn intDiv(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
4069 // TODO is this a performance issue? maybe we should try the operation without
4070 // resorting to BigInt first.
4071 var lhs_space: Value.BigIntSpace = undefined;
4072 var rhs_space: Value.BigIntSpace = undefined;
4073 const lhs_bigint = lhs.toBigInt(&lhs_space);
4074 const rhs_bigint = rhs.toBigInt(&rhs_space);
4075 const limbs_q = try allocator.alloc(
4076 std.math.big.Limb,
4077 lhs_bigint.limbs.len + rhs_bigint.limbs.len + 1,
4078 );
4079 const limbs_r = try allocator.alloc(
4080 std.math.big.Limb,
4081 lhs_bigint.limbs.len,
4082 );
4083 const limbs_buffer = try allocator.alloc(
4084 std.math.big.Limb,
4085 std.math.big.int.calcDivLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
4086 );
4087 var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
4088 var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
4089 result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer, null);
4090 const result_limbs = result_q.limbs[0..result_q.len];
4091
4092 if (result_q.positive) {
4093 return Value.Tag.int_big_positive.create(allocator, result_limbs);
4094 } else {
4095 return Value.Tag.int_big_negative.create(allocator, result_limbs);
4096 }
4097}
4098
4333pub fn intMul(allocator: *Allocator, lhs: Value, rhs: Value) !Value {4099pub fn intMul(allocator: *Allocator, lhs: Value, rhs: Value) !Value {
4334 // TODO is this a performance issue? maybe we should try the operation without4100 // TODO is this a performance issue? maybe we should try the operation without
4335 // resorting to BigInt first.4101 // resorting to BigInt first.
...@@ -4423,6 +4189,39 @@ pub fn floatSub(...@@ -4423,6 +4189,39 @@ pub fn floatSub(
4423 }4189 }
4424}4190}
44254191
4192pub fn floatDiv(
4193 arena: *Allocator,
4194 float_type: Type,
4195 src: LazySrcLoc,
4196 lhs: Value,
4197 rhs: Value,
4198) !Value {
4199 switch (float_type.tag()) {
4200 .f16 => {
4201 @panic("TODO add __trunctfhf2 to compiler-rt");
4202 //const lhs_val = lhs.toFloat(f16);
4203 //const rhs_val = rhs.toFloat(f16);
4204 //return Value.Tag.float_16.create(arena, lhs_val / rhs_val);
4205 },
4206 .f32 => {
4207 const lhs_val = lhs.toFloat(f32);
4208 const rhs_val = rhs.toFloat(f32);
4209 return Value.Tag.float_32.create(arena, lhs_val / rhs_val);
4210 },
4211 .f64 => {
4212 const lhs_val = lhs.toFloat(f64);
4213 const rhs_val = rhs.toFloat(f64);
4214 return Value.Tag.float_64.create(arena, lhs_val / rhs_val);
4215 },
4216 .f128, .comptime_float, .c_longdouble => {
4217 const lhs_val = lhs.toFloat(f128);
4218 const rhs_val = rhs.toFloat(f128);
4219 return Value.Tag.float_128.create(arena, lhs_val / rhs_val);
4220 },
4221 else => unreachable,
4222 }
4223}
4224
4426pub fn floatMul(4225pub fn floatMul(
4427 arena: *Allocator,4226 arena: *Allocator,
4428 float_type: Type,4227 float_type: Type,
...@@ -4615,138 +4414,512 @@ pub fn optimizeMode(mod: Module) std.builtin.Mode {...@@ -4615,138 +4414,512 @@ pub fn optimizeMode(mod: Module) std.builtin.Mode {
4615 return mod.comp.bin_file.options.optimize_mode;4414 return mod.comp.bin_file.options.optimize_mode;
4616}4415}
46174416
4618/// Given an identifier token, obtain the string for it.4417fn lockAndClearFileCompileError(mod: *Module, file: *Scope.File) void {
4619/// If the token uses @"" syntax, parses as a string, reports errors if applicable,4418 switch (file.status) {
4620/// and allocates the result within `scope.arena()`.4419 .success_zir, .retryable_failure => {},
4621/// Otherwise, returns a reference to the source code bytes directly.4420 .never_loaded, .parse_failure, .astgen_failure => {
4622/// See also `appendIdentStr` and `parseStrLit`.4421 const lock = mod.comp.mutex.acquire();
4623pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex) InnerError![]const u8 {4422 defer lock.release();
4624 const tree = scope.tree();4423 if (mod.failed_files.swapRemove(file)) |entry| {
4625 const token_tags = tree.tokens.items(.tag);4424 if (entry.value) |msg| msg.destroy(mod.gpa); // Delete previous error message.
4626 assert(token_tags[token] == .identifier);4425 }
4627 const ident_name = tree.tokenSlice(token);4426 },
4628 if (!mem.startsWith(u8, ident_name, "@")) {4427 }
4629 return ident_name;
4630 }
4631 var buf: ArrayListUnmanaged(u8) = .{};
4632 defer buf.deinit(mod.gpa);
4633 try parseStrLit(mod, scope, token, &buf, ident_name, 1);
4634 const duped = try scope.arena().dupe(u8, buf.items);
4635 return duped;
4636}4428}
46374429
4638/// `scope` is only used for error reporting.4430pub const SwitchProngSrc = union(enum) {
4639/// The string is stored in `arena` regardless of whether it uses @"" syntax.4431 scalar: u32,
4640pub fn identifierTokenStringTreeArena(4432 multi: Multi,
4641 mod: *Module,4433 range: Multi,
4642 scope: *Scope,4434
4643 token: ast.TokenIndex,4435 pub const Multi = struct {
4644 tree: *const ast.Tree,4436 prong: u32,
4645 arena: *Allocator,4437 item: u32,
4646) InnerError![]u8 {4438 };
4647 const token_tags = tree.tokens.items(.tag);4439
4648 assert(token_tags[token] == .identifier);4440 pub const RangeExpand = enum { none, first, last };
4649 const ident_name = tree.tokenSlice(token);4441
4650 if (!mem.startsWith(u8, ident_name, "@")) {4442 /// This function is intended to be called only when it is certain that we need
4651 return arena.dupe(u8, ident_name);4443 /// the LazySrcLoc in order to emit a compile error.
4652 }4444 pub fn resolve(
4653 var buf: ArrayListUnmanaged(u8) = .{};4445 prong_src: SwitchProngSrc,
4654 defer buf.deinit(mod.gpa);4446 gpa: *Allocator,
4655 try parseStrLit(mod, scope, token, &buf, ident_name, 1);4447 decl: *Decl,
4656 return arena.dupe(u8, buf.items);4448 switch_node_offset: i32,
4449 range_expand: RangeExpand,
4450 ) LazySrcLoc {
4451 @setCold(true);
4452 const tree = decl.namespace.file_scope.getTree(gpa) catch |err| {
4453 // In this case we emit a warning + a less precise source location.
4454 log.warn("unable to load {s}: {s}", .{
4455 decl.namespace.file_scope.sub_file_path, @errorName(err),
4456 });
4457 return LazySrcLoc{ .node_offset = 0 };
4458 };
4459 const switch_node = decl.relativeToNodeIndex(switch_node_offset);
4460 const main_tokens = tree.nodes.items(.main_token);
4461 const node_datas = tree.nodes.items(.data);
4462 const node_tags = tree.nodes.items(.tag);
4463 const extra = tree.extraData(node_datas[switch_node].rhs, ast.Node.SubRange);
4464 const case_nodes = tree.extra_data[extra.start..extra.end];
4465
4466 var multi_i: u32 = 0;
4467 var scalar_i: u32 = 0;
4468 for (case_nodes) |case_node| {
4469 const case = switch (node_tags[case_node]) {
4470 .switch_case_one => tree.switchCaseOne(case_node),
4471 .switch_case => tree.switchCase(case_node),
4472 else => unreachable,
4473 };
4474 if (case.ast.values.len == 0)
4475 continue;
4476 if (case.ast.values.len == 1 and
4477 node_tags[case.ast.values[0]] == .identifier and
4478 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
4479 {
4480 continue;
4481 }
4482 const is_multi = case.ast.values.len != 1 or
4483 node_tags[case.ast.values[0]] == .switch_range;
4484
4485 switch (prong_src) {
4486 .scalar => |i| if (!is_multi and i == scalar_i) return LazySrcLoc{
4487 .node_offset = decl.nodeIndexToRelative(case.ast.values[0]),
4488 },
4489 .multi => |s| if (is_multi and s.prong == multi_i) {
4490 var item_i: u32 = 0;
4491 for (case.ast.values) |item_node| {
4492 if (node_tags[item_node] == .switch_range) continue;
4493
4494 if (item_i == s.item) return LazySrcLoc{
4495 .node_offset = decl.nodeIndexToRelative(item_node),
4496 };
4497 item_i += 1;
4498 } else unreachable;
4499 },
4500 .range => |s| if (is_multi and s.prong == multi_i) {
4501 var range_i: u32 = 0;
4502 for (case.ast.values) |range| {
4503 if (node_tags[range] != .switch_range) continue;
4504
4505 if (range_i == s.item) switch (range_expand) {
4506 .none => return LazySrcLoc{
4507 .node_offset = decl.nodeIndexToRelative(range),
4508 },
4509 .first => return LazySrcLoc{
4510 .node_offset = decl.nodeIndexToRelative(node_datas[range].lhs),
4511 },
4512 .last => return LazySrcLoc{
4513 .node_offset = decl.nodeIndexToRelative(node_datas[range].rhs),
4514 },
4515 };
4516 range_i += 1;
4517 } else unreachable;
4518 },
4519 }
4520 if (is_multi) {
4521 multi_i += 1;
4522 } else {
4523 scalar_i += 1;
4524 }
4525 } else unreachable;
4526 }
4527};
4528
4529pub fn analyzeStructFields(mod: *Module, struct_obj: *Struct) InnerError!void {
4530 const tracy = trace(@src());
4531 defer tracy.end();
4532
4533 const gpa = mod.gpa;
4534 const zir = struct_obj.owner_decl.namespace.file_scope.zir;
4535 const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended;
4536 assert(extended.opcode == .struct_decl);
4537 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
4538 var extra_index: usize = extended.operand;
4539
4540 const src: LazySrcLoc = .{ .node_offset = struct_obj.node_offset };
4541 extra_index += @boolToInt(small.has_src_node);
4542
4543 const body_len = if (small.has_body_len) blk: {
4544 const body_len = zir.extra[extra_index];
4545 extra_index += 1;
4546 break :blk body_len;
4547 } else 0;
4548
4549 const fields_len = if (small.has_fields_len) blk: {
4550 const fields_len = zir.extra[extra_index];
4551 extra_index += 1;
4552 break :blk fields_len;
4553 } else 0;
4554
4555 const decls_len = if (small.has_decls_len) decls_len: {
4556 const decls_len = zir.extra[extra_index];
4557 extra_index += 1;
4558 break :decls_len decls_len;
4559 } else 0;
4560
4561 // Skip over decls.
4562 var decls_it = zir.declIteratorInner(extra_index, decls_len);
4563 while (decls_it.next()) |_| {}
4564 extra_index = decls_it.extra_index;
4565
4566 const body = zir.extra[extra_index..][0..body_len];
4567 if (fields_len == 0) {
4568 assert(body.len == 0);
4569 return;
4570 }
4571 extra_index += body.len;
4572
4573 var decl_arena = struct_obj.owner_decl.value_arena.?.promote(gpa);
4574 defer struct_obj.owner_decl.value_arena.?.* = decl_arena.state;
4575
4576 try struct_obj.fields.ensureCapacity(&decl_arena.allocator, fields_len);
4577
4578 // We create a block for the field type instructions because they
4579 // may need to reference Decls from inside the struct namespace.
4580 // Within the field type, default value, and alignment expressions, the "owner decl"
4581 // should be the struct itself. Thus we need a new Sema.
4582 var sema: Sema = .{
4583 .mod = mod,
4584 .gpa = gpa,
4585 .arena = &decl_arena.allocator,
4586 .code = zir,
4587 .owner_decl = struct_obj.owner_decl,
4588 .namespace = &struct_obj.namespace,
4589 .owner_func = null,
4590 .func = null,
4591 .param_inst_list = &.{},
4592 };
4593 defer sema.deinit();
4594
4595 var block: Scope.Block = .{
4596 .parent = null,
4597 .sema = &sema,
4598 .src_decl = struct_obj.owner_decl,
4599 .instructions = .{},
4600 .inlining = null,
4601 .is_comptime = true,
4602 };
4603 defer assert(block.instructions.items.len == 0); // should all be comptime instructions
4604
4605 if (body.len != 0) {
4606 _ = try sema.analyzeBody(&block, body);
4607 }
4608
4609 const bits_per_field = 4;
4610 const fields_per_u32 = 32 / bits_per_field;
4611 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
4612 var bit_bag_index: usize = extra_index;
4613 extra_index += bit_bags_count;
4614 var cur_bit_bag: u32 = undefined;
4615 var field_i: u32 = 0;
4616 while (field_i < fields_len) : (field_i += 1) {
4617 if (field_i % fields_per_u32 == 0) {
4618 cur_bit_bag = zir.extra[bit_bag_index];
4619 bit_bag_index += 1;
4620 }
4621 const has_align = @truncate(u1, cur_bit_bag) != 0;
4622 cur_bit_bag >>= 1;
4623 const has_default = @truncate(u1, cur_bit_bag) != 0;
4624 cur_bit_bag >>= 1;
4625 const is_comptime = @truncate(u1, cur_bit_bag) != 0;
4626 cur_bit_bag >>= 1;
4627 const unused = @truncate(u1, cur_bit_bag) != 0;
4628 cur_bit_bag >>= 1;
4629
4630 _ = unused;
4631
4632 const field_name_zir = zir.nullTerminatedString(zir.extra[extra_index]);
4633 extra_index += 1;
4634 const field_type_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
4635 extra_index += 1;
4636
4637 // This string needs to outlive the ZIR code.
4638 const field_name = try decl_arena.allocator.dupe(u8, field_name_zir);
4639 if (field_type_ref == .none) {
4640 return mod.fail(&block.base, src, "TODO: implement anytype struct field", .{});
4641 }
4642 const field_ty: Type = if (field_type_ref == .none)
4643 Type.initTag(.noreturn)
4644 else
4645 // TODO: if we need to report an error here, use a source location
4646 // that points to this type expression rather than the struct.
4647 // But only resolve the source location if we need to emit a compile error.
4648 try sema.resolveType(&block, src, field_type_ref);
4649
4650 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
4651 assert(!gop.found_existing);
4652 gop.entry.value = .{
4653 .ty = field_ty,
4654 .abi_align = Value.initTag(.abi_align_default),
4655 .default_val = Value.initTag(.unreachable_value),
4656 .is_comptime = is_comptime,
4657 .offset = undefined,
4658 };
4659
4660 if (has_align) {
4661 const align_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
4662 extra_index += 1;
4663 // TODO: if we need to report an error here, use a source location
4664 // that points to this alignment expression rather than the struct.
4665 // But only resolve the source location if we need to emit a compile error.
4666 gop.entry.value.abi_align = (try sema.resolveInstConst(&block, src, align_ref)).val;
4667 }
4668 if (has_default) {
4669 const default_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
4670 extra_index += 1;
4671 // TODO: if we need to report an error here, use a source location
4672 // that points to this default value expression rather than the struct.
4673 // But only resolve the source location if we need to emit a compile error.
4674 gop.entry.value.default_val = (try sema.resolveInstConst(&block, src, default_ref)).val;
4675 }
4676 }
4657}4677}
46584678
4659/// Given an identifier token, obtain the string for it (possibly parsing as a string4679pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {
4660/// literal if it is @"" syntax), and append the string to `buf`.4680 const tracy = trace(@src());
4661/// See also `identifierTokenString` and `parseStrLit`.4681 defer tracy.end();
4662pub fn appendIdentStr(4682
4663 mod: *Module,4683 const gpa = mod.gpa;
4664 scope: *Scope,4684 const zir = union_obj.owner_decl.namespace.file_scope.zir;
4665 token: ast.TokenIndex,4685 const extended = zir.instructions.items(.data)[union_obj.zir_index].extended;
4666 buf: *ArrayListUnmanaged(u8),4686 assert(extended.opcode == .union_decl);
4667) InnerError!void {4687 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);
4668 const tree = scope.tree();4688 var extra_index: usize = extended.operand;
4669 const token_tags = tree.tokens.items(.tag);4689
4670 assert(token_tags[token] == .identifier);4690 const src: LazySrcLoc = .{ .node_offset = union_obj.node_offset };
4671 const ident_name = tree.tokenSlice(token);4691 extra_index += @boolToInt(small.has_src_node);
4672 if (!mem.startsWith(u8, ident_name, "@")) {4692
4673 return buf.appendSlice(mod.gpa, ident_name);4693 const tag_type_ref = if (small.has_tag_type) blk: {
4674 } else {4694 const tag_type_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
4675 return mod.parseStrLit(scope, token, buf, ident_name, 1);4695 extra_index += 1;
4696 break :blk tag_type_ref;
4697 } else .none;
4698
4699 const body_len = if (small.has_body_len) blk: {
4700 const body_len = zir.extra[extra_index];
4701 extra_index += 1;
4702 break :blk body_len;
4703 } else 0;
4704
4705 const fields_len = if (small.has_fields_len) blk: {
4706 const fields_len = zir.extra[extra_index];
4707 extra_index += 1;
4708 break :blk fields_len;
4709 } else 0;
4710
4711 const decls_len = if (small.has_decls_len) decls_len: {
4712 const decls_len = zir.extra[extra_index];
4713 extra_index += 1;
4714 break :decls_len decls_len;
4715 } else 0;
4716
4717 // Skip over decls.
4718 var decls_it = zir.declIteratorInner(extra_index, decls_len);
4719 while (decls_it.next()) |_| {}
4720 extra_index = decls_it.extra_index;
4721
4722 const body = zir.extra[extra_index..][0..body_len];
4723 if (fields_len == 0) {
4724 assert(body.len == 0);
4725 return;
4726 }
4727 extra_index += body.len;
4728
4729 var decl_arena = union_obj.owner_decl.value_arena.?.promote(gpa);
4730 defer union_obj.owner_decl.value_arena.?.* = decl_arena.state;
4731
4732 try union_obj.fields.ensureCapacity(&decl_arena.allocator, fields_len);
4733
4734 // We create a block for the field type instructions because they
4735 // may need to reference Decls from inside the struct namespace.
4736 // Within the field type, default value, and alignment expressions, the "owner decl"
4737 // should be the struct itself. Thus we need a new Sema.
4738 var sema: Sema = .{
4739 .mod = mod,
4740 .gpa = gpa,
4741 .arena = &decl_arena.allocator,
4742 .code = zir,
4743 .owner_decl = union_obj.owner_decl,
4744 .namespace = &union_obj.namespace,
4745 .owner_func = null,
4746 .func = null,
4747 .param_inst_list = &.{},
4748 };
4749 defer sema.deinit();
4750
4751 var block: Scope.Block = .{
4752 .parent = null,
4753 .sema = &sema,
4754 .src_decl = union_obj.owner_decl,
4755 .instructions = .{},
4756 .inlining = null,
4757 .is_comptime = true,
4758 };
4759 defer assert(block.instructions.items.len == 0); // should all be comptime instructions
4760
4761 if (body.len != 0) {
4762 _ = try sema.analyzeBody(&block, body);
4763 }
4764
4765 const bits_per_field = 4;
4766 const fields_per_u32 = 32 / bits_per_field;
4767 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
4768 var bit_bag_index: usize = extra_index;
4769 extra_index += bit_bags_count;
4770 var cur_bit_bag: u32 = undefined;
4771 var field_i: u32 = 0;
4772 while (field_i < fields_len) : (field_i += 1) {
4773 if (field_i % fields_per_u32 == 0) {
4774 cur_bit_bag = zir.extra[bit_bag_index];
4775 bit_bag_index += 1;
4776 }
4777 const has_type = @truncate(u1, cur_bit_bag) != 0;
4778 cur_bit_bag >>= 1;
4779 const has_align = @truncate(u1, cur_bit_bag) != 0;
4780 cur_bit_bag >>= 1;
4781 const has_tag = @truncate(u1, cur_bit_bag) != 0;
4782 cur_bit_bag >>= 1;
4783 const unused = @truncate(u1, cur_bit_bag) != 0;
4784 cur_bit_bag >>= 1;
4785
4786 const field_name_zir = zir.nullTerminatedString(zir.extra[extra_index]);
4787 extra_index += 1;
4788
4789 const field_type_ref: Zir.Inst.Ref = if (has_type) blk: {
4790 const field_type_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
4791 extra_index += 1;
4792 break :blk field_type_ref;
4793 } else .none;
4794
4795 const align_ref: Zir.Inst.Ref = if (has_align) blk: {
4796 const align_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
4797 extra_index += 1;
4798 break :blk align_ref;
4799 } else .none;
4800
4801 const tag_ref: Zir.Inst.Ref = if (has_tag) blk: {
4802 const tag_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
4803 extra_index += 1;
4804 break :blk tag_ref;
4805 } else .none;
4806
4807 // This string needs to outlive the ZIR code.
4808 const field_name = try decl_arena.allocator.dupe(u8, field_name_zir);
4809 const field_ty: Type = if (field_type_ref == .none)
4810 Type.initTag(.void)
4811 else
4812 // TODO: if we need to report an error here, use a source location
4813 // that points to this type expression rather than the union.
4814 // But only resolve the source location if we need to emit a compile error.
4815 try sema.resolveType(&block, src, field_type_ref);
4816
4817 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
4818 assert(!gop.found_existing);
4819 gop.entry.value = .{
4820 .ty = field_ty,
4821 .abi_align = Value.initTag(.abi_align_default),
4822 };
4823
4824 if (align_ref != .none) {
4825 // TODO: if we need to report an error here, use a source location
4826 // that points to this alignment expression rather than the struct.
4827 // But only resolve the source location if we need to emit a compile error.
4828 gop.entry.value.abi_align = (try sema.resolveInstConst(&block, src, align_ref)).val;
4829 }
4676 }4830 }
4831
4832 // TODO resolve the union tag_type_ref
4677}4833}
46784834
4679/// Appends the result to `buf`.4835/// Called from `performAllTheWork`, after all AstGen workers have finished,
4680pub fn parseStrLit(4836/// and before the main semantic analysis loop begins.
4681 mod: *Module,4837pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {
4682 scope: *Scope,4838 // Ultimately, the goal is to queue up `analyze_decl` tasks in the work queue
4683 token: ast.TokenIndex,4839 // for the outdated decls, but we cannot queue up the tasks until after
4684 buf: *ArrayListUnmanaged(u8),4840 // we find out which ones have been deleted, otherwise there would be
4685 bytes: []const u8,4841 // deleted Decl pointers in the work queue.
4686 offset: u32,4842 var outdated_decls = std.AutoArrayHashMap(*Decl, void).init(mod.gpa);
4687) InnerError!void {4843 defer outdated_decls.deinit();
4688 const tree = scope.tree();4844 for (mod.import_table.items()) |import_table_entry| {
4689 const token_starts = tree.tokens.items(.start);4845 const file = import_table_entry.value;
4690 const raw_string = bytes[offset..];4846
4691 var buf_managed = buf.toManaged(mod.gpa);4847 try outdated_decls.ensureUnusedCapacity(file.outdated_decls.items.len);
4692 const result = std.zig.string_literal.parseAppend(&buf_managed, raw_string);4848 for (file.outdated_decls.items) |decl| {
4693 buf.* = buf_managed.toUnmanaged();4849 outdated_decls.putAssumeCapacity(decl, {});
4694 switch (try result) {4850 }
4695 .success => return,4851 file.outdated_decls.clearRetainingCapacity();
4696 .invalid_character => |bad_index| {4852
4697 return mod.failOff(4853 // Handle explicitly deleted decls from the source code. This is one of two
4698 scope,4854 // places that Decl deletions happen. The other is in `Compilation`, after
4699 token_starts[token] + offset + @intCast(u32, bad_index),4855 // `performAllTheWork`, where we iterate over `Module.deletion_set` and
4700 "invalid string literal character: '{c}'",4856 // delete Decls which are no longer referenced.
4701 .{raw_string[bad_index]},4857 // If a Decl is explicitly deleted from source, and also no longer referenced,
4702 );4858 // it may be both in this `deleted_decls` set, as well as in the
4703 },4859 // `Module.deletion_set`. To avoid deleting it twice, we remove it from the
4704 .expected_hex_digits => |bad_index| {4860 // deletion set at this time.
4705 return mod.failOff(4861 for (file.deleted_decls.items) |decl| {
4706 scope,4862 log.debug("deleted from source: {*} ({s})", .{ decl, decl.name });
4707 token_starts[token] + offset + @intCast(u32, bad_index),4863
4708 "expected hex digits after '\\x'",4864 // Remove from the namespace it resides in, preserving declaration order.
4709 .{},4865 assert(decl.zir_decl_index != 0);
4710 );4866 _ = decl.namespace.decls.orderedRemove(mem.spanZ(decl.name));
4711 },4867
4712 .invalid_hex_escape => |bad_index| {4868 try mod.clearDecl(decl, &outdated_decls);
4713 return mod.failOff(4869 decl.destroy(mod);
4714 scope,4870 }
4715 token_starts[token] + offset + @intCast(u32, bad_index),4871 file.deleted_decls.clearRetainingCapacity();
4716 "invalid hex digit: '{c}'",4872 }
4717 .{raw_string[bad_index]},4873 // Finally we can queue up re-analysis tasks after we have processed
4718 );4874 // the deleted decls.
4719 },4875 for (outdated_decls.items()) |entry| {
4720 .invalid_unicode_escape => |bad_index| {4876 try mod.markOutdatedDecl(entry.key);
4721 return mod.failOff(
4722 scope,
4723 token_starts[token] + offset + @intCast(u32, bad_index),
4724 "invalid unicode digit: '{c}'",
4725 .{raw_string[bad_index]},
4726 );
4727 },
4728 .missing_matching_rbrace => |bad_index| {
4729 return mod.failOff(
4730 scope,
4731 token_starts[token] + offset + @intCast(u32, bad_index),
4732 "missing matching '}}' character",
4733 .{},
4734 );
4735 },
4736 .expected_unicode_digits => |bad_index| {
4737 return mod.failOff(
4738 scope,
4739 token_starts[token] + offset + @intCast(u32, bad_index),
4740 "expected unicode digits after '\\u'",
4741 .{},
4742 );
4743 },
4744 }4877 }
4745}4878}
47464879
4747pub fn unloadFile(mod: *Module, file_scope: *Scope.File) void {4880/// Called from `Compilation.update`, after everything is done, just before
4748 if (file_scope.status == .unloaded_parse_failure) {4881/// reporting compile errors. In this function we emit exported symbol collision
4749 mod.failed_files.swapRemove(file_scope).?.value.destroy(mod.gpa);4882/// errors and communicate exported symbols to the linker backend.
4883pub fn processExports(mod: *Module) !void {
4884 const gpa = mod.gpa;
4885 // Map symbol names to `Export` for name collision detection.
4886 var symbol_exports: std.StringArrayHashMapUnmanaged(*Export) = .{};
4887 defer symbol_exports.deinit(gpa);
4888
4889 for (mod.decl_exports.items()) |entry| {
4890 const exported_decl = entry.key;
4891 const exports = entry.value;
4892 for (exports) |new_export| {
4893 const gop = try symbol_exports.getOrPut(gpa, new_export.options.name);
4894 if (gop.found_existing) {
4895 new_export.status = .failed_retryable;
4896 try mod.failed_exports.ensureUnusedCapacity(gpa, 1);
4897 const src_loc = new_export.getSrcLoc();
4898 const msg = try ErrorMsg.create(gpa, src_loc, "exported symbol collision: {s}", .{
4899 new_export.options.name,
4900 });
4901 errdefer msg.destroy(gpa);
4902 const other_export = gop.entry.value;
4903 const other_src_loc = other_export.getSrcLoc();
4904 try mod.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{});
4905 mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
4906 new_export.status = .failed;
4907 } else {
4908 gop.entry.value = new_export;
4909 }
4910 }
4911 mod.comp.bin_file.updateDeclExports(mod, exported_decl, exports) catch |err| switch (err) {
4912 error.OutOfMemory => return error.OutOfMemory,
4913 else => {
4914 const new_export = exports[0];
4915 new_export.status = .failed_retryable;
4916 try mod.failed_exports.ensureUnusedCapacity(gpa, 1);
4917 const src_loc = new_export.getSrcLoc();
4918 const msg = try ErrorMsg.create(gpa, src_loc, "unable to export: {s}", .{
4919 @errorName(err),
4920 });
4921 mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
4922 },
4923 };
4750 }4924 }
4751 file_scope.unload(mod.gpa);
4752}4925}
src/Package.zig-11
...@@ -11,22 +11,15 @@ const Module = @import("Module.zig");...@@ -11,22 +11,15 @@ const Module = @import("Module.zig");
1111
12pub const Table = std.StringHashMapUnmanaged(*Package);12pub const Table = std.StringHashMapUnmanaged(*Package);
1313
14pub const root_namespace_hash: Module.Scope.NameHash = .{
15 0, 0, 6, 6, 6, 0, 0, 0,
16 6, 9, 0, 0, 0, 4, 2, 0,
17};
18
19root_src_directory: Compilation.Directory,14root_src_directory: Compilation.Directory,
20/// Relative to `root_src_directory`. May contain path separators.15/// Relative to `root_src_directory`. May contain path separators.
21root_src_path: []const u8,16root_src_path: []const u8,
22table: Table = .{},17table: Table = .{},
23parent: ?*Package = null,18parent: ?*Package = null,
24namespace_hash: Module.Scope.NameHash,
25/// Whether to free `root_src_directory` on `destroy`.19/// Whether to free `root_src_directory` on `destroy`.
26root_src_directory_owned: bool = false,20root_src_directory_owned: bool = false,
2721
28/// Allocate a Package. No references to the slices passed are kept.22/// Allocate a Package. No references to the slices passed are kept.
29/// Don't forget to set `namespace_hash` later.
30pub fn create(23pub fn create(
31 gpa: *Allocator,24 gpa: *Allocator,
32 /// Null indicates the current working directory25 /// Null indicates the current working directory
...@@ -50,7 +43,6 @@ pub fn create(...@@ -50,7 +43,6 @@ pub fn create(
50 },43 },
51 .root_src_path = owned_src_path,44 .root_src_path = owned_src_path,
52 .root_src_directory_owned = true,45 .root_src_directory_owned = true,
53 .namespace_hash = undefined,
54 };46 };
5547
56 return ptr;48 return ptr;
...@@ -82,14 +74,12 @@ pub fn createWithDir(...@@ -82,14 +74,12 @@ pub fn createWithDir(
82 },74 },
83 .root_src_directory_owned = true,75 .root_src_directory_owned = true,
84 .root_src_path = owned_src_path,76 .root_src_path = owned_src_path,
85 .namespace_hash = undefined,
86 };77 };
87 } else {78 } else {
88 ptr.* = .{79 ptr.* = .{
89 .root_src_directory = directory,80 .root_src_directory = directory,
90 .root_src_directory_owned = false,81 .root_src_directory_owned = false,
91 .root_src_path = owned_src_path,82 .root_src_path = owned_src_path,
92 .namespace_hash = undefined,
93 };83 };
94 }84 }
95 return ptr;85 return ptr;
...@@ -129,6 +119,5 @@ pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package)...@@ -129,6 +119,5 @@ pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package)
129pub fn addAndAdopt(parent: *Package, gpa: *Allocator, name: []const u8, child: *Package) !void {119pub fn addAndAdopt(parent: *Package, gpa: *Allocator, name: []const u8, child: *Package) !void {
130 assert(child.parent == null); // make up your mind, who is the parent??120 assert(child.parent == null); // make up your mind, who is the parent??
131 child.parent = parent;121 child.parent = parent;
132 child.namespace_hash = std.zig.hashName(parent.namespace_hash, ":", name);
133 return parent.add(gpa, name, child);122 return parent.add(gpa, name, child);
134}123}
src/RangeSet.zig+1-1
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
2const Order = std.math.Order;2const Order = std.math.Order;
3const Value = @import("value.zig").Value;3const Value = @import("value.zig").Value;
4const RangeSet = @This();4const RangeSet = @This();
5const SwitchProngSrc = @import("AstGen.zig").SwitchProngSrc;5const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;
66
7ranges: std.ArrayList(Range),7ranges: std.ArrayList(Range),
88
src/Sema.zig+2857-975
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1//! Semantic analysis of ZIR instructions.1//! Semantic analysis of ZIR instructions.
2//! Shared to every Block. Stored on the stack.2//! Shared to every Block. Stored on the stack.
3//! State used for compiling a `zir.Code` into TZIR.3//! State used for compiling a `Zir` into AIR.
4//! Transforms untyped ZIR instructions into semantically-analyzed TZIR instructions.4//! Transforms untyped ZIR instructions into semantically-analyzed AIR instructions.
5//! Does type checking, comptime control flow, and safety-check generation.5//! Does type checking, comptime control flow, and safety-check generation.
6//! This is the the heart of the Zig compiler.6//! This is the the heart of the Zig compiler.
77
...@@ -10,13 +10,15 @@ mod: *Module,...@@ -10,13 +10,15 @@ mod: *Module,
10gpa: *Allocator,10gpa: *Allocator,
11/// Points to the arena allocator of the Decl.11/// Points to the arena allocator of the Decl.
12arena: *Allocator,12arena: *Allocator,
13code: zir.Code,13code: Zir,
14/// Maps ZIR to TZIR.14/// Maps ZIR to AIR.
15inst_map: []*Inst,15inst_map: InstMap = .{},
16/// When analyzing an inline function call, owner_decl is the Decl of the caller16/// When analyzing an inline function call, owner_decl is the Decl of the caller
17/// and `src_decl` of `Scope.Block` is the `Decl` of the callee.17/// and `src_decl` of `Scope.Block` is the `Decl` of the callee.
18/// This `Decl` owns the arena memory of this `Sema`.18/// This `Decl` owns the arena memory of this `Sema`.
19owner_decl: *Decl,19owner_decl: *Decl,
20/// How to look up decl names.
21namespace: *Scope.Namespace,
20/// For an inline or comptime function call, this will be the root parent function22/// For an inline or comptime function call, this will be the root parent function
21/// which contains the callsite. Corresponds to `owner_decl`.23/// which contains the callsite. Corresponds to `owner_decl`.
22owner_func: ?*Module.Fn,24owner_func: ?*Module.Fn,
...@@ -24,9 +26,9 @@ owner_func: ?*Module.Fn,...@@ -24,9 +26,9 @@ owner_func: ?*Module.Fn,
24/// This starts out the same as `owner_func` and then diverges in the case of26/// This starts out the same as `owner_func` and then diverges in the case of
25/// an inline or comptime function call.27/// an inline or comptime function call.
26func: ?*Module.Fn,28func: ?*Module.Fn,
27/// For now, TZIR requires arg instructions to be the first N instructions in the29/// For now, AIR requires arg instructions to be the first N instructions in the
28/// TZIR code. We store references here for the purpose of `resolveInst`.30/// AIR code. We store references here for the purpose of `resolveInst`.
29/// This can get reworked with TZIR memory layout changes, into simply:31/// This can get reworked with AIR memory layout changes, into simply:
30/// > Denormalized data to make `resolveInst` faster. This is 0 if not inside a function,32/// > Denormalized data to make `resolveInst` faster. This is 0 if not inside a function,
31/// > otherwise it is the number of parameters of the function.33/// > otherwise it is the number of parameters of the function.
32/// > param_count: u3234/// > param_count: u32
...@@ -38,6 +40,7 @@ branch_count: u32 = 0,...@@ -38,6 +40,7 @@ branch_count: u32 = 0,
38/// access to the source location set by the previous instruction which did40/// access to the source location set by the previous instruction which did
39/// contain a mapped source location.41/// contain a mapped source location.
40src: LazySrcLoc = .{ .token_offset = 0 },42src: LazySrcLoc = .{ .token_offset = 0 },
43next_arg_index: usize = 0,
4144
42const std = @import("std");45const std = @import("std");
43const mem = std.mem;46const mem = std.mem;
...@@ -50,7 +53,7 @@ const Value = @import("value.zig").Value;...@@ -50,7 +53,7 @@ const Value = @import("value.zig").Value;
50const Type = @import("type.zig").Type;53const Type = @import("type.zig").Type;
51const TypedValue = @import("TypedValue.zig");54const TypedValue = @import("TypedValue.zig");
52const ir = @import("ir.zig");55const ir = @import("ir.zig");
53const zir = @import("zir.zig");56const Zir = @import("Zir.zig");
54const Module = @import("Module.zig");57const Module = @import("Module.zig");
55const Inst = ir.Inst;58const Inst = ir.Inst;
56const Body = ir.Body;59const Body = ir.Body;
...@@ -60,34 +63,52 @@ const InnerError = Module.InnerError;...@@ -60,34 +63,52 @@ const InnerError = Module.InnerError;
60const Decl = Module.Decl;63const Decl = Module.Decl;
61const LazySrcLoc = Module.LazySrcLoc;64const LazySrcLoc = Module.LazySrcLoc;
62const RangeSet = @import("RangeSet.zig");65const RangeSet = @import("RangeSet.zig");
63const AstGen = @import("AstGen.zig");66const target_util = @import("target.zig");
6467
65pub fn root(sema: *Sema, root_block: *Scope.Block) !zir.Inst.Index {68pub const InstMap = std.AutoHashMapUnmanaged(Zir.Inst.Index, *ir.Inst);
66 const inst_data = sema.code.instructions.items(.data)[0].pl_node;
67 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
68 const root_body = sema.code.extra[extra.end..][0..extra.data.body_len];
69 return sema.analyzeBody(root_block, root_body);
70}
7169
72pub fn rootAsRef(sema: *Sema, root_block: *Scope.Block) !zir.Inst.Ref {70pub fn deinit(sema: *Sema) void {
73 const break_inst = try sema.root(root_block);71 sema.inst_map.deinit(sema.gpa);
74 return sema.code.instructions.items(.data)[break_inst].@"break".operand;72 sema.* = undefined;
75}73}
7674
77/// Assumes that `root_block` ends with `break_inline`.75pub fn analyzeFnBody(
78pub fn rootAsType(sema: *Sema, root_block: *Scope.Block) !Type {76 sema: *Sema,
79 assert(root_block.is_comptime);77 block: *Scope.Block,
80 const zir_inst_ref = try sema.rootAsRef(root_block);78 fn_body_inst: Zir.Inst.Index,
81 // Source location is unneeded because resolveConstValue must have already79) InnerError!void {
82 // been successfully called when coercing the value to a type, from the80 const tags = sema.code.instructions.items(.tag);
83 // result location.81 const datas = sema.code.instructions.items(.data);
84 return sema.resolveType(root_block, .unneeded, zir_inst_ref);82 const body: []const Zir.Inst.Index = switch (tags[fn_body_inst]) {
83 .func, .func_inferred => blk: {
84 const inst_data = datas[fn_body_inst].pl_node;
85 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
86 const param_types_len = extra.data.param_types_len;
87 const body = sema.code.extra[extra.end + param_types_len ..][0..extra.data.body_len];
88 break :blk body;
89 },
90 .extended => blk: {
91 const extended = datas[fn_body_inst].extended;
92 assert(extended.opcode == .func);
93 const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, extended.operand);
94 const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
95 var extra_index: usize = extra.end;
96 extra_index += @boolToInt(small.has_lib_name);
97 extra_index += @boolToInt(small.has_cc);
98 extra_index += @boolToInt(small.has_align);
99 extra_index += extra.data.param_types_len;
100 const body = sema.code.extra[extra_index..][0..extra.data.body_len];
101 break :blk body;
102 },
103 else => unreachable,
104 };
105 _ = try sema.analyzeBody(block, body);
85}106}
86107
87/// Returns only the result from the body that is specified.108/// Returns only the result from the body that is specified.
88/// Only appropriate to call when it is determined at comptime that this body109/// Only appropriate to call when it is determined at comptime that this body
89/// has no peers.110/// has no peers.
90fn resolveBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Index) InnerError!*Inst {111fn resolveBody(sema: *Sema, block: *Scope.Block, body: []const Zir.Inst.Index) InnerError!*Inst {
91 const break_inst = try sema.analyzeBody(block, body);112 const break_inst = try sema.analyzeBody(block, body);
92 const operand_ref = sema.code.instructions.items(.data)[break_inst].@"break".operand;113 const operand_ref = sema.code.instructions.items(.data)[break_inst].@"break".operand;
93 return sema.resolveInst(operand_ref);114 return sema.resolveInst(operand_ref);
...@@ -97,25 +118,25 @@ fn resolveBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Index) I...@@ -97,25 +118,25 @@ fn resolveBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Index) I
97/// return type of `analyzeBody` so that we can tail call them.118/// return type of `analyzeBody` so that we can tail call them.
98/// Only appropriate to return when the instruction is known to be NoReturn119/// Only appropriate to return when the instruction is known to be NoReturn
99/// solely based on the ZIR tag.120/// solely based on the ZIR tag.
100const always_noreturn: InnerError!zir.Inst.Index = @as(zir.Inst.Index, undefined);121const always_noreturn: InnerError!Zir.Inst.Index = @as(Zir.Inst.Index, undefined);
101122
102/// This function is the main loop of `Sema` and it can be used in two different ways:123/// This function is the main loop of `Sema` and it can be used in two different ways:
103/// * The traditional way where there are N breaks out of the block and peer type124/// * The traditional way where there are N breaks out of the block and peer type
104/// resolution is done on the break operands. In this case, the `zir.Inst.Index`125/// resolution is done on the break operands. In this case, the `Zir.Inst.Index`
105/// part of the return value will be `undefined`, and callsites should ignore it,126/// part of the return value will be `undefined`, and callsites should ignore it,
106/// finding the block result value via the block scope.127/// finding the block result value via the block scope.
107/// * The "flat" way. There is only 1 break out of the block, and it is with a `break_inline`128/// * The "flat" way. There is only 1 break out of the block, and it is with a `break_inline`
108/// instruction. In this case, the `zir.Inst.Index` part of the return value will be129/// instruction. In this case, the `Zir.Inst.Index` part of the return value will be
109/// the break instruction. This communicates both which block the break applies to, as130/// the break instruction. This communicates both which block the break applies to, as
110/// well as the operand. No block scope needs to be created for this strategy.131/// well as the operand. No block scope needs to be created for this strategy.
111pub fn analyzeBody(132pub fn analyzeBody(
112 sema: *Sema,133 sema: *Sema,
113 block: *Scope.Block,134 block: *Scope.Block,
114 body: []const zir.Inst.Index,135 body: []const Zir.Inst.Index,
115) InnerError!zir.Inst.Index {136) InnerError!Zir.Inst.Index {
116 // No tracy calls here, to avoid interfering with the tail call mechanism.137 // No tracy calls here, to avoid interfering with the tail call mechanism.
117138
118 const map = block.sema.inst_map;139 const map = &block.sema.inst_map;
119 const tags = block.sema.code.instructions.items(.tag);140 const tags = block.sema.code.instructions.items(.tag);
120 const datas = block.sema.code.instructions.items(.data);141 const datas = block.sema.code.instructions.items(.data);
121142
...@@ -128,166 +149,243 @@ pub fn analyzeBody(...@@ -128,166 +149,243 @@ pub fn analyzeBody(
128 var i: usize = 0;149 var i: usize = 0;
129 while (true) : (i += 1) {150 while (true) : (i += 1) {
130 const inst = body[i];151 const inst = body[i];
131 map[inst] = switch (tags[inst]) {152 const air_inst = switch (tags[inst]) {
132 .elided => continue,153 // zig fmt: off
133154 .arg => try sema.zirArg(block, inst),
134 .add => try sema.zirArithmetic(block, inst),155 .alloc => try sema.zirAlloc(block, inst),
135 .addwrap => try sema.zirArithmetic(block, inst),156 .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),
136 .alloc => try sema.zirAlloc(block, inst),157 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),
137 .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),158 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(block, inst),
138 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),159 .alloc_mut => try sema.zirAllocMut(block, inst),
139 .alloc_mut => try sema.zirAllocMut(block, inst),160 .alloc_comptime => try sema.zirAllocComptime(block, inst),
140 .array_cat => try sema.zirArrayCat(block, inst),161 .anyframe_type => try sema.zirAnyframeType(block, inst),
141 .array_mul => try sema.zirArrayMul(block, inst),162 .array_cat => try sema.zirArrayCat(block, inst),
142 .array_type => try sema.zirArrayType(block, inst),163 .array_mul => try sema.zirArrayMul(block, inst),
143 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),164 .array_type => try sema.zirArrayType(block, inst),
144 .as => try sema.zirAs(block, inst),165 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
145 .as_node => try sema.zirAsNode(block, inst),166 .vector_type => try sema.zirVectorType(block, inst),
146 .@"asm" => try sema.zirAsm(block, inst, false),167 .as => try sema.zirAs(block, inst),
147 .asm_volatile => try sema.zirAsm(block, inst, true),168 .as_node => try sema.zirAsNode(block, inst),
148 .bit_and => try sema.zirBitwise(block, inst, .bit_and),169 .bit_and => try sema.zirBitwise(block, inst, .bit_and),
149 .bit_not => try sema.zirBitNot(block, inst),170 .bit_not => try sema.zirBitNot(block, inst),
150 .bit_or => try sema.zirBitwise(block, inst, .bit_or),171 .bit_or => try sema.zirBitwise(block, inst, .bit_or),
151 .bitcast => try sema.zirBitcast(block, inst),172 .bitcast => try sema.zirBitcast(block, inst),
152 .bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst),173 .bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst),
153 .block => try sema.zirBlock(block, inst),174 .block => try sema.zirBlock(block, inst),
154 .bool_not => try sema.zirBoolNot(block, inst),175 .suspend_block => try sema.zirSuspendBlock(block, inst),
155 .bool_and => try sema.zirBoolOp(block, inst, false),176 .bool_not => try sema.zirBoolNot(block, inst),
156 .bool_or => try sema.zirBoolOp(block, inst, true),177 .bool_and => try sema.zirBoolOp(block, inst, false),
157 .bool_br_and => try sema.zirBoolBr(block, inst, false),178 .bool_or => try sema.zirBoolOp(block, inst, true),
158 .bool_br_or => try sema.zirBoolBr(block, inst, true),179 .bool_br_and => try sema.zirBoolBr(block, inst, false),
159 .call => try sema.zirCall(block, inst, .auto, false),180 .bool_br_or => try sema.zirBoolBr(block, inst, true),
160 .call_chkused => try sema.zirCall(block, inst, .auto, true),181 .c_import => try sema.zirCImport(block, inst),
161 .call_compile_time => try sema.zirCall(block, inst, .compile_time, false),182 .call => try sema.zirCall(block, inst, .auto, false),
162 .call_none => try sema.zirCallNone(block, inst, false),183 .call_chkused => try sema.zirCall(block, inst, .auto, true),
163 .call_none_chkused => try sema.zirCallNone(block, inst, true),184 .call_compile_time => try sema.zirCall(block, inst, .compile_time, false),
164 .cmp_eq => try sema.zirCmp(block, inst, .eq),185 .call_nosuspend => try sema.zirCall(block, inst, .no_async, false),
165 .cmp_gt => try sema.zirCmp(block, inst, .gt),186 .call_async => try sema.zirCall(block, inst, .async_kw, false),
166 .cmp_gte => try sema.zirCmp(block, inst, .gte),187 .cmp_eq => try sema.zirCmp(block, inst, .eq),
167 .cmp_lt => try sema.zirCmp(block, inst, .lt),188 .cmp_gt => try sema.zirCmp(block, inst, .gt),
168 .cmp_lte => try sema.zirCmp(block, inst, .lte),189 .cmp_gte => try sema.zirCmp(block, inst, .gte),
169 .cmp_neq => try sema.zirCmp(block, inst, .neq),190 .cmp_lt => try sema.zirCmp(block, inst, .lt),
170 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),191 .cmp_lte => try sema.zirCmp(block, inst, .lte),
171 .decl_ref => try sema.zirDeclRef(block, inst),192 .cmp_neq => try sema.zirCmp(block, inst, .neq),
172 .decl_val => try sema.zirDeclVal(block, inst),193 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
173 .load => try sema.zirLoad(block, inst),194 .decl_ref => try sema.zirDeclRef(block, inst),
174 .div => try sema.zirArithmetic(block, inst),195 .decl_val => try sema.zirDeclVal(block, inst),
175 .elem_ptr => try sema.zirElemPtr(block, inst),196 .load => try sema.zirLoad(block, inst),
176 .elem_ptr_node => try sema.zirElemPtrNode(block, inst),197 .elem_ptr => try sema.zirElemPtr(block, inst),
177 .elem_val => try sema.zirElemVal(block, inst),198 .elem_ptr_node => try sema.zirElemPtrNode(block, inst),
178 .elem_val_node => try sema.zirElemValNode(block, inst),199 .elem_val => try sema.zirElemVal(block, inst),
179 .enum_literal => try sema.zirEnumLiteral(block, inst),200 .elem_val_node => try sema.zirElemValNode(block, inst),
180 .enum_literal_small => try sema.zirEnumLiteralSmall(block, inst),201 .elem_type => try sema.zirElemType(block, inst),
181 .enum_to_int => try sema.zirEnumToInt(block, inst),202 .enum_literal => try sema.zirEnumLiteral(block, inst),
182 .int_to_enum => try sema.zirIntToEnum(block, inst),203 .enum_to_int => try sema.zirEnumToInt(block, inst),
183 .err_union_code => try sema.zirErrUnionCode(block, inst),204 .int_to_enum => try sema.zirIntToEnum(block, inst),
184 .err_union_code_ptr => try sema.zirErrUnionCodePtr(block, inst),205 .err_union_code => try sema.zirErrUnionCode(block, inst),
185 .err_union_payload_safe => try sema.zirErrUnionPayload(block, inst, true),206 .err_union_code_ptr => try sema.zirErrUnionCodePtr(block, inst),
186 .err_union_payload_safe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, true),207 .err_union_payload_safe => try sema.zirErrUnionPayload(block, inst, true),
187 .err_union_payload_unsafe => try sema.zirErrUnionPayload(block, inst, false),208 .err_union_payload_safe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, true),
209 .err_union_payload_unsafe => try sema.zirErrUnionPayload(block, inst, false),
188 .err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, false),210 .err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, false),
189 .error_union_type => try sema.zirErrorUnionType(block, inst),211 .error_union_type => try sema.zirErrorUnionType(block, inst),
190 .error_value => try sema.zirErrorValue(block, inst),212 .error_value => try sema.zirErrorValue(block, inst),
191 .error_to_int => try sema.zirErrorToInt(block, inst),213 .error_to_int => try sema.zirErrorToInt(block, inst),
192 .int_to_error => try sema.zirIntToError(block, inst),214 .int_to_error => try sema.zirIntToError(block, inst),
193 .field_ptr => try sema.zirFieldPtr(block, inst),215 .field_ptr => try sema.zirFieldPtr(block, inst),
194 .field_ptr_named => try sema.zirFieldPtrNamed(block, inst),216 .field_ptr_named => try sema.zirFieldPtrNamed(block, inst),
195 .field_val => try sema.zirFieldVal(block, inst),217 .field_val => try sema.zirFieldVal(block, inst),
196 .field_val_named => try sema.zirFieldValNamed(block, inst),218 .field_val_named => try sema.zirFieldValNamed(block, inst),
197 .floatcast => try sema.zirFloatcast(block, inst),219 .func => try sema.zirFunc(block, inst, false),
198 .fn_type => try sema.zirFnType(block, inst, false),220 .func_inferred => try sema.zirFunc(block, inst, true),
199 .fn_type_cc => try sema.zirFnTypeCc(block, inst, false),221 .import => try sema.zirImport(block, inst),
200 .fn_type_cc_var_args => try sema.zirFnTypeCc(block, inst, true),222 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
201 .fn_type_var_args => try sema.zirFnType(block, inst, true),223 .int => try sema.zirInt(block, inst),
202 .has_decl => try sema.zirHasDecl(block, inst),224 .int_big => try sema.zirIntBig(block, inst),
203 .import => try sema.zirImport(block, inst),225 .float => try sema.zirFloat(block, inst),
204 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),226 .float128 => try sema.zirFloat128(block, inst),
205 .int => try sema.zirInt(block, inst),227 .int_type => try sema.zirIntType(block, inst),
206 .float => try sema.zirFloat(block, inst),228 .is_err => try sema.zirIsErr(block, inst),
207 .float128 => try sema.zirFloat128(block, inst),229 .is_err_ptr => try sema.zirIsErrPtr(block, inst),
208 .int_type => try sema.zirIntType(block, inst),230 .is_non_null => try sema.zirIsNull(block, inst, true),
209 .intcast => try sema.zirIntcast(block, inst),231 .is_non_null_ptr => try sema.zirIsNullPtr(block, inst, true),
210 .is_err => try sema.zirIsErr(block, inst),232 .is_null => try sema.zirIsNull(block, inst, false),
211 .is_err_ptr => try sema.zirIsErrPtr(block, inst),233 .is_null_ptr => try sema.zirIsNullPtr(block, inst, false),
212 .is_non_null => try sema.zirIsNull(block, inst, true),234 .loop => try sema.zirLoop(block, inst),
213 .is_non_null_ptr => try sema.zirIsNullPtr(block, inst, true),235 .merge_error_sets => try sema.zirMergeErrorSets(block, inst),
214 .is_null => try sema.zirIsNull(block, inst, false),236 .negate => try sema.zirNegate(block, inst, .sub),
215 .is_null_ptr => try sema.zirIsNullPtr(block, inst, false),237 .negate_wrap => try sema.zirNegate(block, inst, .subwrap),
216 .loop => try sema.zirLoop(block, inst),238 .optional_payload_safe => try sema.zirOptionalPayload(block, inst, true),
217 .merge_error_sets => try sema.zirMergeErrorSets(block, inst),239 .optional_payload_safe_ptr => try sema.zirOptionalPayloadPtr(block, inst, true),
240 .optional_payload_unsafe => try sema.zirOptionalPayload(block, inst, false),
241 .optional_payload_unsafe_ptr => try sema.zirOptionalPayloadPtr(block, inst, false),
242 .optional_type => try sema.zirOptionalType(block, inst),
243 .param_type => try sema.zirParamType(block, inst),
244 .ptr_type => try sema.zirPtrType(block, inst),
245 .ptr_type_simple => try sema.zirPtrTypeSimple(block, inst),
246 .ref => try sema.zirRef(block, inst),
247 .shl => try sema.zirShl(block, inst),
248 .shr => try sema.zirShr(block, inst),
249 .slice_end => try sema.zirSliceEnd(block, inst),
250 .slice_sentinel => try sema.zirSliceSentinel(block, inst),
251 .slice_start => try sema.zirSliceStart(block, inst),
252 .str => try sema.zirStr(block, inst),
253 .switch_block => try sema.zirSwitchBlock(block, inst, false, .none),
254 .switch_block_multi => try sema.zirSwitchBlockMulti(block, inst, false, .none),
255 .switch_block_else => try sema.zirSwitchBlock(block, inst, false, .@"else"),
256 .switch_block_else_multi => try sema.zirSwitchBlockMulti(block, inst, false, .@"else"),
257 .switch_block_under => try sema.zirSwitchBlock(block, inst, false, .under),
258 .switch_block_under_multi => try sema.zirSwitchBlockMulti(block, inst, false, .under),
259 .switch_block_ref => try sema.zirSwitchBlock(block, inst, true, .none),
260 .switch_block_ref_multi => try sema.zirSwitchBlockMulti(block, inst, true, .none),
261 .switch_block_ref_else => try sema.zirSwitchBlock(block, inst, true, .@"else"),
262 .switch_block_ref_else_multi => try sema.zirSwitchBlockMulti(block, inst, true, .@"else"),
263 .switch_block_ref_under => try sema.zirSwitchBlock(block, inst, true, .under),
264 .switch_block_ref_under_multi => try sema.zirSwitchBlockMulti(block, inst, true, .under),
265 .switch_capture => try sema.zirSwitchCapture(block, inst, false, false),
266 .switch_capture_ref => try sema.zirSwitchCapture(block, inst, false, true),
267 .switch_capture_multi => try sema.zirSwitchCapture(block, inst, true, false),
268 .switch_capture_multi_ref => try sema.zirSwitchCapture(block, inst, true, true),
269 .switch_capture_else => try sema.zirSwitchCaptureElse(block, inst, false),
270 .switch_capture_else_ref => try sema.zirSwitchCaptureElse(block, inst, true),
271 .type_info => try sema.zirTypeInfo(block, inst),
272 .size_of => try sema.zirSizeOf(block, inst),
273 .bit_size_of => try sema.zirBitSizeOf(block, inst),
274 .typeof => try sema.zirTypeof(block, inst),
275 .typeof_elem => try sema.zirTypeofElem(block, inst),
276 .log2_int_type => try sema.zirLog2IntType(block, inst),
277 .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),
278 .xor => try sema.zirBitwise(block, inst, .xor),
279 .struct_init_empty => try sema.zirStructInitEmpty(block, inst),
280 .struct_init => try sema.zirStructInit(block, inst, false),
281 .struct_init_ref => try sema.zirStructInit(block, inst, true),
282 .struct_init_anon => try sema.zirStructInitAnon(block, inst, false),
283 .struct_init_anon_ref => try sema.zirStructInitAnon(block, inst, true),
284 .array_init => try sema.zirArrayInit(block, inst, false),
285 .array_init_ref => try sema.zirArrayInit(block, inst, true),
286 .array_init_anon => try sema.zirArrayInitAnon(block, inst, false),
287 .array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true),
288 .union_init_ptr => try sema.zirUnionInitPtr(block, inst),
289 .field_type => try sema.zirFieldType(block, inst),
290 .field_type_ref => try sema.zirFieldTypeRef(block, inst),
291 .ptr_to_int => try sema.zirPtrToInt(block, inst),
292 .align_of => try sema.zirAlignOf(block, inst),
293 .bool_to_int => try sema.zirBoolToInt(block, inst),
294 .embed_file => try sema.zirEmbedFile(block, inst),
295 .error_name => try sema.zirErrorName(block, inst),
296 .tag_name => try sema.zirTagName(block, inst),
297 .reify => try sema.zirReify(block, inst),
298 .type_name => try sema.zirTypeName(block, inst),
299 .frame_type => try sema.zirFrameType(block, inst),
300 .frame_size => try sema.zirFrameSize(block, inst),
301 .float_to_int => try sema.zirFloatToInt(block, inst),
302 .int_to_float => try sema.zirIntToFloat(block, inst),
303 .int_to_ptr => try sema.zirIntToPtr(block, inst),
304 .float_cast => try sema.zirFloatCast(block, inst),
305 .int_cast => try sema.zirIntCast(block, inst),
306 .err_set_cast => try sema.zirErrSetCast(block, inst),
307 .ptr_cast => try sema.zirPtrCast(block, inst),
308 .truncate => try sema.zirTruncate(block, inst),
309 .align_cast => try sema.zirAlignCast(block, inst),
310 .has_decl => try sema.zirHasDecl(block, inst),
311 .has_field => try sema.zirHasField(block, inst),
312 .clz => try sema.zirClz(block, inst),
313 .ctz => try sema.zirCtz(block, inst),
314 .pop_count => try sema.zirPopCount(block, inst),
315 .byte_swap => try sema.zirByteSwap(block, inst),
316 .bit_reverse => try sema.zirBitReverse(block, inst),
317 .div_exact => try sema.zirDivExact(block, inst),
318 .div_floor => try sema.zirDivFloor(block, inst),
319 .div_trunc => try sema.zirDivTrunc(block, inst),
320 .mod => try sema.zirMod(block, inst),
321 .rem => try sema.zirRem(block, inst),
322 .shl_exact => try sema.zirShlExact(block, inst),
323 .shr_exact => try sema.zirShrExact(block, inst),
324 .bit_offset_of => try sema.zirBitOffsetOf(block, inst),
325 .byte_offset_of => try sema.zirByteOffsetOf(block, inst),
326 .cmpxchg_strong => try sema.zirCmpxchg(block, inst),
327 .cmpxchg_weak => try sema.zirCmpxchg(block, inst),
328 .splat => try sema.zirSplat(block, inst),
329 .reduce => try sema.zirReduce(block, inst),
330 .shuffle => try sema.zirShuffle(block, inst),
331 .atomic_load => try sema.zirAtomicLoad(block, inst),
332 .atomic_rmw => try sema.zirAtomicRmw(block, inst),
333 .atomic_store => try sema.zirAtomicStore(block, inst),
334 .mul_add => try sema.zirMulAdd(block, inst),
335 .builtin_call => try sema.zirBuiltinCall(block, inst),
336 .field_ptr_type => try sema.zirFieldPtrType(block, inst),
337 .field_parent_ptr => try sema.zirFieldParentPtr(block, inst),
338 .memcpy => try sema.zirMemcpy(block, inst),
339 .memset => try sema.zirMemset(block, inst),
340 .builtin_async_call => try sema.zirBuiltinAsyncCall(block, inst),
341 .@"resume" => try sema.zirResume(block, inst),
342 .@"await" => try sema.zirAwait(block, inst, false),
343 .await_nosuspend => try sema.zirAwait(block, inst, true),
344 .extended => try sema.zirExtended(block, inst),
345
346 .sqrt => try sema.zirUnaryMath(block, inst),
347 .sin => try sema.zirUnaryMath(block, inst),
348 .cos => try sema.zirUnaryMath(block, inst),
349 .exp => try sema.zirUnaryMath(block, inst),
350 .exp2 => try sema.zirUnaryMath(block, inst),
351 .log => try sema.zirUnaryMath(block, inst),
352 .log2 => try sema.zirUnaryMath(block, inst),
353 .log10 => try sema.zirUnaryMath(block, inst),
354 .fabs => try sema.zirUnaryMath(block, inst),
355 .floor => try sema.zirUnaryMath(block, inst),
356 .ceil => try sema.zirUnaryMath(block, inst),
357 .trunc => try sema.zirUnaryMath(block, inst),
358 .round => try sema.zirUnaryMath(block, inst),
359
360 .opaque_decl => try sema.zirOpaqueDecl(block, inst, .parent),
361 .opaque_decl_anon => try sema.zirOpaqueDecl(block, inst, .anon),
362 .opaque_decl_func => try sema.zirOpaqueDecl(block, inst, .func),
363 .error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent),
364 .error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon),
365 .error_set_decl_func => try sema.zirErrorSetDecl(block, inst, .func),
366
367 .add => try sema.zirArithmetic(block, inst),
368 .addwrap => try sema.zirArithmetic(block, inst),
369 .div => try sema.zirArithmetic(block, inst),
218 .mod_rem => try sema.zirArithmetic(block, inst),370 .mod_rem => try sema.zirArithmetic(block, inst),
219 .mul => try sema.zirArithmetic(block, inst),371 .mul => try sema.zirArithmetic(block, inst),
220 .mulwrap => try sema.zirArithmetic(block, inst),372 .mulwrap => try sema.zirArithmetic(block, inst),
221 .negate => try sema.zirNegate(block, inst, .sub),373 .sub => try sema.zirArithmetic(block, inst),
222 .negate_wrap => try sema.zirNegate(block, inst, .subwrap),
223 .optional_payload_safe => try sema.zirOptionalPayload(block, inst, true),
224 .optional_payload_safe_ptr => try sema.zirOptionalPayloadPtr(block, inst, true),
225 .optional_payload_unsafe => try sema.zirOptionalPayload(block, inst, false),
226 .optional_payload_unsafe_ptr => try sema.zirOptionalPayloadPtr(block, inst, false),
227 .optional_type => try sema.zirOptionalType(block, inst),
228 .optional_type_from_ptr_elem => try sema.zirOptionalTypeFromPtrElem(block, inst),
229 .param_type => try sema.zirParamType(block, inst),
230 .ptr_type => try sema.zirPtrType(block, inst),
231 .ptr_type_simple => try sema.zirPtrTypeSimple(block, inst),
232 .ptrtoint => try sema.zirPtrtoint(block, inst),
233 .ref => try sema.zirRef(block, inst),
234 .ret_ptr => try sema.zirRetPtr(block, inst),
235 .ret_type => try sema.zirRetType(block, inst),
236 .shl => try sema.zirShl(block, inst),
237 .shr => try sema.zirShr(block, inst),
238 .slice_end => try sema.zirSliceEnd(block, inst),
239 .slice_sentinel => try sema.zirSliceSentinel(block, inst),
240 .slice_start => try sema.zirSliceStart(block, inst),
241 .str => try sema.zirStr(block, inst),
242 .sub => try sema.zirArithmetic(block, inst),
243 .subwrap => try sema.zirArithmetic(block, inst),374 .subwrap => try sema.zirArithmetic(block, inst),
244 .switch_block => try sema.zirSwitchBlock(block, inst, false, .none),
245 .switch_block_multi => try sema.zirSwitchBlockMulti(block, inst, false, .none),
246 .switch_block_else => try sema.zirSwitchBlock(block, inst, false, .@"else"),
247 .switch_block_else_multi => try sema.zirSwitchBlockMulti(block, inst, false, .@"else"),
248 .switch_block_under => try sema.zirSwitchBlock(block, inst, false, .under),
249 .switch_block_under_multi => try sema.zirSwitchBlockMulti(block, inst, false, .under),
250 .switch_block_ref => try sema.zirSwitchBlock(block, inst, true, .none),
251 .switch_block_ref_multi => try sema.zirSwitchBlockMulti(block, inst, true, .none),
252 .switch_block_ref_else => try sema.zirSwitchBlock(block, inst, true, .@"else"),
253 .switch_block_ref_else_multi => try sema.zirSwitchBlockMulti(block, inst, true, .@"else"),
254 .switch_block_ref_under => try sema.zirSwitchBlock(block, inst, true, .under),
255 .switch_block_ref_under_multi => try sema.zirSwitchBlockMulti(block, inst, true, .under),
256 .switch_capture => try sema.zirSwitchCapture(block, inst, false, false),
257 .switch_capture_ref => try sema.zirSwitchCapture(block, inst, false, true),
258 .switch_capture_multi => try sema.zirSwitchCapture(block, inst, true, false),
259 .switch_capture_multi_ref => try sema.zirSwitchCapture(block, inst, true, true),
260 .switch_capture_else => try sema.zirSwitchCaptureElse(block, inst, false),
261 .switch_capture_else_ref => try sema.zirSwitchCaptureElse(block, inst, true),
262 .type_info => try sema.zirTypeInfo(block, inst),
263 .typeof => try sema.zirTypeof(block, inst),
264 .typeof_elem => try sema.zirTypeofElem(block, inst),
265 .typeof_peer => try sema.zirTypeofPeer(block, inst),
266 .xor => try sema.zirBitwise(block, inst, .xor),
267 .struct_init_empty => try sema.zirStructInitEmpty(block, inst),
268 .struct_init => try sema.zirStructInit(block, inst),
269 .field_type => try sema.zirFieldType(block, inst),
270
271 .struct_decl => try sema.zirStructDecl(block, inst, .Auto),
272 .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed),
273 .struct_decl_extern => try sema.zirStructDecl(block, inst, .Extern),
274 .enum_decl => try sema.zirEnumDecl(block, inst, false),
275 .enum_decl_nonexhaustive => try sema.zirEnumDecl(block, inst, true),
276 .union_decl => try sema.zirUnionDecl(block, inst),
277 .opaque_decl => try sema.zirOpaqueDecl(block, inst),
278375
279 // Instructions that we know to *always* be noreturn based solely on their tag.376 // Instructions that we know to *always* be noreturn based solely on their tag.
280 // These functions match the return type of analyzeBody so that we can377 // These functions match the return type of analyzeBody so that we can
281 // tail call them here.378 // tail call them here.
282 .condbr => return sema.zirCondbr(block, inst),379 .break_inline => return inst,
283 .@"break" => return sema.zirBreak(block, inst),380 .condbr => return sema.zirCondbr(block, inst),
284 .break_inline => return inst,381 .@"break" => return sema.zirBreak(block, inst),
285 .compile_error => return sema.zirCompileError(block, inst),382 .compile_error => return sema.zirCompileError(block, inst),
286 .ret_coerce => return sema.zirRetTok(block, inst, true),383 .ret_coerce => return sema.zirRetTok(block, inst, true),
287 .ret_node => return sema.zirRetNode(block, inst),384 .ret_node => return sema.zirRetNode(block, inst),
288 .ret_tok => return sema.zirRetTok(block, inst, false),
289 .@"unreachable" => return sema.zirUnreachable(block, inst),385 .@"unreachable" => return sema.zirUnreachable(block, inst),
290 .repeat => return sema.zirRepeat(block, inst),386 .repeat => return sema.zirRepeat(block, inst),
387 .panic => return sema.zirPanic(block, inst),
388 // zig fmt: on
291389
292 // Instructions that we know can *never* be noreturn based solely on390 // Instructions that we know can *never* be noreturn based solely on
293 // their tag. We avoid needlessly checking if they are noreturn and391 // their tag. We avoid needlessly checking if they are noreturn and
...@@ -298,8 +396,12 @@ pub fn analyzeBody(...@@ -298,8 +396,12 @@ pub fn analyzeBody(
298 try sema.zirBreakpoint(block, inst);396 try sema.zirBreakpoint(block, inst);
299 continue;397 continue;
300 },398 },
301 .dbg_stmt_node => {399 .fence => {
302 try sema.zirDbgStmtNode(block, inst);400 try sema.zirFence(block, inst);
401 continue;
402 },
403 .dbg_stmt => {
404 try sema.zirDbgStmt(block, inst);
303 continue;405 continue;
304 },406 },
305 .ensure_err_payload_void => {407 .ensure_err_payload_void => {
...@@ -314,10 +416,6 @@ pub fn analyzeBody(...@@ -314,10 +416,6 @@ pub fn analyzeBody(
314 try sema.zirEnsureResultUsed(block, inst);416 try sema.zirEnsureResultUsed(block, inst);
315 continue;417 continue;
316 },418 },
317 .compile_log => {
318 try sema.zirCompileLog(block, inst);
319 continue;
320 },
321 .set_eval_branch_quota => {419 .set_eval_branch_quota => {
322 try sema.zirSetEvalBranchQuota(block, inst);420 try sema.zirSetEvalBranchQuota(block, inst);
323 continue;421 continue;
...@@ -346,10 +444,30 @@ pub fn analyzeBody(...@@ -346,10 +444,30 @@ pub fn analyzeBody(
346 try sema.zirValidateStructInitPtr(block, inst);444 try sema.zirValidateStructInitPtr(block, inst);
347 continue;445 continue;
348 },446 },
447 .validate_array_init_ptr => {
448 try sema.zirValidateArrayInitPtr(block, inst);
449 continue;
450 },
349 .@"export" => {451 .@"export" => {
350 try sema.zirExport(block, inst);452 try sema.zirExport(block, inst);
351 continue;453 continue;
352 },454 },
455 .set_align_stack => {
456 try sema.zirSetAlignStack(block, inst);
457 continue;
458 },
459 .set_cold => {
460 try sema.zirSetAlignStack(block, inst);
461 continue;
462 },
463 .set_float_mode => {
464 try sema.zirSetFloatMode(block, inst);
465 continue;
466 },
467 .set_runtime_safety => {
468 try sema.zirSetRuntimeSafety(block, inst);
469 continue;
470 },
353471
354 // Special case instructions to handle comptime control flow.472 // Special case instructions to handle comptime control flow.
355 .repeat_inline => {473 .repeat_inline => {
...@@ -362,7 +480,7 @@ pub fn analyzeBody(...@@ -362,7 +480,7 @@ pub fn analyzeBody(
362 .block_inline => blk: {480 .block_inline => blk: {
363 // Directly analyze the block body without introducing a new block.481 // Directly analyze the block body without introducing a new block.
364 const inst_data = datas[inst].pl_node;482 const inst_data = datas[inst].pl_node;
365 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);483 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
366 const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];484 const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
367 const break_inst = try sema.analyzeBody(block, inline_body);485 const break_inst = try sema.analyzeBody(block, inline_body);
368 const break_data = datas[break_inst].@"break";486 const break_data = datas[break_inst].@"break";
...@@ -375,7 +493,7 @@ pub fn analyzeBody(...@@ -375,7 +493,7 @@ pub fn analyzeBody(
375 .condbr_inline => blk: {493 .condbr_inline => blk: {
376 const inst_data = datas[inst].pl_node;494 const inst_data = datas[inst].pl_node;
377 const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node };495 const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node };
378 const extra = sema.code.extraData(zir.Inst.CondBr, inst_data.payload_index);496 const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
379 const then_body = sema.code.extra[extra.end..][0..extra.data.then_body_len];497 const then_body = sema.code.extra[extra.end..][0..extra.data.then_body_len];
380 const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];498 const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
381 const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition);499 const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition);
...@@ -389,53 +507,87 @@ pub fn analyzeBody(...@@ -389,53 +507,87 @@ pub fn analyzeBody(
389 }507 }
390 },508 },
391 };509 };
392 if (map[inst].ty.isNoReturn())510 if (air_inst.ty.isNoReturn())
393 return always_noreturn;511 return always_noreturn;
512 try map.putNoClobber(sema.gpa, inst, air_inst);
394 }513 }
395}514}
396515
397/// TODO when we rework TZIR memory layout, this function will no longer have a possible error.516fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
398pub fn resolveInst(sema: *Sema, zir_ref: zir.Inst.Ref) error{OutOfMemory}!*ir.Inst {517 const extended = sema.code.instructions.items(.data)[inst].extended;
518 switch (extended.opcode) {
519 // zig fmt: off
520 .func => return sema.zirFuncExtended( block, extended, inst),
521 .variable => return sema.zirVarExtended( block, extended),
522 .struct_decl => return sema.zirStructDecl( block, extended, inst),
523 .enum_decl => return sema.zirEnumDecl( block, extended),
524 .union_decl => return sema.zirUnionDecl( block, extended, inst),
525 .ret_ptr => return sema.zirRetPtr( block, extended),
526 .ret_type => return sema.zirRetType( block, extended),
527 .this => return sema.zirThis( block, extended),
528 .ret_addr => return sema.zirRetAddr( block, extended),
529 .builtin_src => return sema.zirBuiltinSrc( block, extended),
530 .error_return_trace => return sema.zirErrorReturnTrace( block, extended),
531 .frame => return sema.zirFrame( block, extended),
532 .frame_address => return sema.zirFrameAddress( block, extended),
533 .alloc => return sema.zirAllocExtended( block, extended),
534 .builtin_extern => return sema.zirBuiltinExtern( block, extended),
535 .@"asm" => return sema.zirAsm( block, extended),
536 .typeof_peer => return sema.zirTypeofPeer( block, extended),
537 .compile_log => return sema.zirCompileLog( block, extended),
538 .add_with_overflow => return sema.zirOverflowArithmetic(block, extended),
539 .sub_with_overflow => return sema.zirOverflowArithmetic(block, extended),
540 .mul_with_overflow => return sema.zirOverflowArithmetic(block, extended),
541 .shl_with_overflow => return sema.zirOverflowArithmetic(block, extended),
542 .c_undef => return sema.zirCUndef( block, extended),
543 .c_include => return sema.zirCInclude( block, extended),
544 .c_define => return sema.zirCDefine( block, extended),
545 .wasm_memory_size => return sema.zirWasmMemorySize( block, extended),
546 .wasm_memory_grow => return sema.zirWasmMemoryGrow( block, extended),
547 // zig fmt: on
548 }
549}
550
551/// TODO when we rework AIR memory layout, this function will no longer have a possible error.
552pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) error{OutOfMemory}!*ir.Inst {
399 var i: usize = @enumToInt(zir_ref);553 var i: usize = @enumToInt(zir_ref);
400554
401 // First section of indexes correspond to a set number of constant values.555 // First section of indexes correspond to a set number of constant values.
402 if (i < zir.Inst.Ref.typed_value_map.len) {556 if (i < Zir.Inst.Ref.typed_value_map.len) {
403 // TODO when we rework TZIR memory layout, this function can be as simple as:557 // TODO when we rework AIR memory layout, this function can be as simple as:
404 // if (zir_ref < zir.const_inst_list.len + sema.param_count)558 // if (zir_ref < Zir.const_inst_list.len + sema.param_count)
405 // return zir_ref;559 // return zir_ref;
406 // Until then we allocate memory for a new, mutable `ir.Inst` to match what560 // Until then we allocate memory for a new, mutable `ir.Inst` to match what
407 // TZIR expects.561 // AIR expects.
408 return sema.mod.constInst(sema.arena, .unneeded, zir.Inst.Ref.typed_value_map[i]);562 return sema.mod.constInst(sema.arena, .unneeded, Zir.Inst.Ref.typed_value_map[i]);
409 }
410 i -= zir.Inst.Ref.typed_value_map.len;
411
412 // Next section of indexes correspond to function parameters, if any.
413 if (i < sema.param_inst_list.len) {
414 return sema.param_inst_list[i];
415 }563 }
416 i -= sema.param_inst_list.len;564 i -= Zir.Inst.Ref.typed_value_map.len;
417565
418 // Finally, the last section of indexes refers to the map of ZIR=>TZIR.566 // Finally, the last section of indexes refers to the map of ZIR=>AIR.
419 return sema.inst_map[i];567 return sema.inst_map.get(@intCast(u32, i)).?;
420}568}
421569
422fn resolveConstString(570fn resolveConstString(
423 sema: *Sema,571 sema: *Sema,
424 block: *Scope.Block,572 block: *Scope.Block,
425 src: LazySrcLoc,573 src: LazySrcLoc,
426 zir_ref: zir.Inst.Ref,574 zir_ref: Zir.Inst.Ref,
427) ![]u8 {575) ![]u8 {
428 const tzir_inst = try sema.resolveInst(zir_ref);576 const air_inst = try sema.resolveInst(zir_ref);
429 const wanted_type = Type.initTag(.const_slice_u8);577 const wanted_type = Type.initTag(.const_slice_u8);
430 const coerced_inst = try sema.coerce(block, wanted_type, tzir_inst, src);578 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
431 const val = try sema.resolveConstValue(block, src, coerced_inst);579 const val = try sema.resolveConstValue(block, src, coerced_inst);
432 return val.toAllocatedBytes(sema.arena);580 return val.toAllocatedBytes(sema.arena);
433}581}
434582
435fn resolveType(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, zir_ref: zir.Inst.Ref) !Type {583pub fn resolveType(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type {
436 const tzir_inst = try sema.resolveInst(zir_ref);584 const air_inst = try sema.resolveInst(zir_ref);
585 return sema.resolveAirAsType(block, src, air_inst);
586}
587
588fn resolveAirAsType(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, air_inst: *ir.Inst) !Type {
437 const wanted_type = Type.initTag(.@"type");589 const wanted_type = Type.initTag(.@"type");
438 const coerced_inst = try sema.coerce(block, wanted_type, tzir_inst, src);590 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
439 const val = try sema.resolveConstValue(block, src, coerced_inst);591 const val = try sema.resolveConstValue(block, src, coerced_inst);
440 return val.toType(sema.arena);592 return val.toType(sema.arena);
441}593}
...@@ -446,7 +598,7 @@ fn resolveConstValue(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, base: *i...@@ -446,7 +598,7 @@ fn resolveConstValue(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, base: *i
446}598}
447599
448fn resolveDefinedValue(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, base: *ir.Inst) !?Value {600fn resolveDefinedValue(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, base: *ir.Inst) !?Value {
449 if (base.value()) |val| {601 if (try sema.resolvePossiblyUndefinedValue(block, src, base)) |val| {
450 if (val.isUndef()) {602 if (val.isUndef()) {
451 return sema.failWithUseOfUndef(block, src);603 return sema.failWithUseOfUndef(block, src);
452 }604 }
...@@ -455,6 +607,19 @@ fn resolveDefinedValue(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, base:...@@ -455,6 +607,19 @@ fn resolveDefinedValue(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, base:
455 return null;607 return null;
456}608}
457609
610fn resolvePossiblyUndefinedValue(
611 sema: *Sema,
612 block: *Scope.Block,
613 src: LazySrcLoc,
614 base: *ir.Inst,
615) !?Value {
616 if (try sema.typeHasOnePossibleValue(block, src, base.ty)) |opv| {
617 return opv;
618 }
619 const inst = base.castTag(.constant) orelse return null;
620 return inst.val;
621}
622
458fn failWithNeededComptime(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) InnerError {623fn failWithNeededComptime(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) InnerError {
459 return sema.mod.fail(&block.base, src, "unable to resolve comptime value", .{});624 return sema.mod.fail(&block.base, src, "unable to resolve comptime value", .{});
460}625}
...@@ -470,12 +635,12 @@ fn resolveAlreadyCoercedInt(...@@ -470,12 +635,12 @@ fn resolveAlreadyCoercedInt(
470 sema: *Sema,635 sema: *Sema,
471 block: *Scope.Block,636 block: *Scope.Block,
472 src: LazySrcLoc,637 src: LazySrcLoc,
473 zir_ref: zir.Inst.Ref,638 zir_ref: Zir.Inst.Ref,
474 comptime Int: type,639 comptime Int: type,
475) !Int {640) !Int {
476 comptime assert(@typeInfo(Int).Int.bits <= 64);641 comptime assert(@typeInfo(Int).Int.bits <= 64);
477 const tzir_inst = try sema.resolveInst(zir_ref);642 const air_inst = try sema.resolveInst(zir_ref);
478 const val = try sema.resolveConstValue(block, src, tzir_inst);643 const val = try sema.resolveConstValue(block, src, air_inst);
479 switch (@typeInfo(Int).Int.signedness) {644 switch (@typeInfo(Int).Int.signedness) {
480 .signed => return @intCast(Int, val.toSignedInt()),645 .signed => return @intCast(Int, val.toSignedInt()),
481 .unsigned => return @intCast(Int, val.toUnsignedInt()),646 .unsigned => return @intCast(Int, val.toUnsignedInt()),
...@@ -486,189 +651,470 @@ fn resolveInt(...@@ -486,189 +651,470 @@ fn resolveInt(
486 sema: *Sema,651 sema: *Sema,
487 block: *Scope.Block,652 block: *Scope.Block,
488 src: LazySrcLoc,653 src: LazySrcLoc,
489 zir_ref: zir.Inst.Ref,654 zir_ref: Zir.Inst.Ref,
490 dest_type: Type,655 dest_type: Type,
491) !u64 {656) !u64 {
492 const tzir_inst = try sema.resolveInst(zir_ref);657 const air_inst = try sema.resolveInst(zir_ref);
493 const coerced = try sema.coerce(block, dest_type, tzir_inst, src);658 const coerced = try sema.coerce(block, dest_type, air_inst, src);
494 const val = try sema.resolveConstValue(block, src, coerced);659 const val = try sema.resolveConstValue(block, src, coerced);
495660
496 return val.toUnsignedInt();661 return val.toUnsignedInt();
497}662}
498663
499fn resolveInstConst(664pub fn resolveInstConst(
500 sema: *Sema,665 sema: *Sema,
501 block: *Scope.Block,666 block: *Scope.Block,
502 src: LazySrcLoc,667 src: LazySrcLoc,
503 zir_ref: zir.Inst.Ref,668 zir_ref: Zir.Inst.Ref,
504) InnerError!TypedValue {669) InnerError!TypedValue {
505 const tzir_inst = try sema.resolveInst(zir_ref);670 const air_inst = try sema.resolveInst(zir_ref);
506 const val = try sema.resolveConstValue(block, src, tzir_inst);671 const val = try sema.resolveConstValue(block, src, air_inst);
507 return TypedValue{672 return TypedValue{
508 .ty = tzir_inst.ty,673 .ty = air_inst.ty,
509 .val = val,674 .val = val,
510 };675 };
511}676}
512677
513fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {678fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
514 const tracy = trace(@src());679 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
515 defer tracy.end();680 const src = inst_data.src();
516 return sema.mod.fail(&block.base, sema.src, "TODO implement zir_sema.zirBitcastResultPtr", .{});681 return sema.mod.fail(&block.base, src, "TODO implement zir_sema.zirBitcastResultPtr", .{});
517}682}
518683
519fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {684fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
520 const tracy = trace(@src());685 const tracy = trace(@src());
521 defer tracy.end();686 defer tracy.end();
522 return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{});687 return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{});
523}688}
524689
690pub fn analyzeStructDecl(
691 sema: *Sema,
692 new_decl: *Decl,
693 inst: Zir.Inst.Index,
694 struct_obj: *Module.Struct,
695) InnerError!void {
696 const extended = sema.code.instructions.items(.data)[inst].extended;
697 assert(extended.opcode == .struct_decl);
698 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
699
700 var extra_index: usize = extended.operand;
701 extra_index += @boolToInt(small.has_src_node);
702 extra_index += @boolToInt(small.has_body_len);
703 extra_index += @boolToInt(small.has_fields_len);
704 const decls_len = if (small.has_decls_len) blk: {
705 const decls_len = sema.code.extra[extra_index];
706 extra_index += 1;
707 break :blk decls_len;
708 } else 0;
709
710 _ = try sema.mod.scanNamespace(&struct_obj.namespace, extra_index, decls_len, new_decl);
711}
712
525fn zirStructDecl(713fn zirStructDecl(
526 sema: *Sema,714 sema: *Sema,
527 block: *Scope.Block,715 block: *Scope.Block,
528 inst: zir.Inst.Index,716 extended: Zir.Inst.Extended.InstData,
529 layout: std.builtin.TypeInfo.ContainerLayout,717 inst: Zir.Inst.Index,
530) InnerError!*Inst {718) InnerError!*Inst {
531 const tracy = trace(@src());719 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
532 defer tracy.end();720 const src: LazySrcLoc = if (small.has_src_node) blk: {
533721 const node_offset = @bitCast(i32, sema.code.extra[extended.operand]);
534 const gpa = sema.gpa;722 break :blk .{ .node_offset = node_offset };
535 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;723 } else sema.src;
536 const src = inst_data.src();
537 const extra = sema.code.extraData(zir.Inst.StructDecl, inst_data.payload_index);
538 const fields_len = extra.data.fields_len;
539 const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable;
540724
541 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);725 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
542 errdefer new_decl_arena.deinit();726 errdefer new_decl_arena.deinit();
543727
544 var fields_map: std.StringArrayHashMapUnmanaged(Module.Struct.Field) = .{};
545 try fields_map.ensureCapacity(&new_decl_arena.allocator, fields_len);
546
547 {
548 var field_index: usize = extra.end + bit_bags_count;
549 var bit_bag_index: usize = extra.end;
550 var cur_bit_bag: u32 = undefined;
551 var field_i: u32 = 0;
552 while (field_i < fields_len) : (field_i += 1) {
553 if (field_i % 16 == 0) {
554 cur_bit_bag = sema.code.extra[bit_bag_index];
555 bit_bag_index += 1;
556 }
557 const has_align = @truncate(u1, cur_bit_bag) != 0;
558 cur_bit_bag >>= 1;
559 const has_default = @truncate(u1, cur_bit_bag) != 0;
560 cur_bit_bag >>= 1;
561
562 const field_name_zir = sema.code.nullTerminatedString(sema.code.extra[field_index]);
563 field_index += 1;
564 const field_type_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
565 field_index += 1;
566
567 // This string needs to outlive the ZIR code.
568 const field_name = try new_decl_arena.allocator.dupe(u8, field_name_zir);
569 // TODO: if we need to report an error here, use a source location
570 // that points to this type expression rather than the struct.
571 // But only resolve the source location if we need to emit a compile error.
572 const field_ty = try sema.resolveType(block, src, field_type_ref);
573
574 const gop = fields_map.getOrPutAssumeCapacity(field_name);
575 assert(!gop.found_existing);
576 gop.entry.value = .{
577 .ty = field_ty,
578 .abi_align = Value.initTag(.abi_align_default),
579 .default_val = Value.initTag(.unreachable_value),
580 };
581
582 if (has_align) {
583 const align_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
584 field_index += 1;
585 // TODO: if we need to report an error here, use a source location
586 // that points to this alignment expression rather than the struct.
587 // But only resolve the source location if we need to emit a compile error.
588 gop.entry.value.abi_align = (try sema.resolveInstConst(block, src, align_ref)).val;
589 }
590 if (has_default) {
591 const default_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
592 field_index += 1;
593 // TODO: if we need to report an error here, use a source location
594 // that points to this default value expression rather than the struct.
595 // But only resolve the source location if we need to emit a compile error.
596 gop.entry.value.default_val = (try sema.resolveInstConst(block, src, default_ref)).val;
597 }
598 }
599 }
600
601 const struct_obj = try new_decl_arena.allocator.create(Module.Struct);728 const struct_obj = try new_decl_arena.allocator.create(Module.Struct);
602 const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);729 const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);
603 const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty);730 const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty);
604 const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{731 const type_name = try sema.createTypeName(block, small.name_strategy);
732 const new_decl = try sema.mod.createAnonymousDeclNamed(&block.base, .{
605 .ty = Type.initTag(.type),733 .ty = Type.initTag(.type),
606 .val = struct_val,734 .val = struct_val,
607 });735 }, type_name);
736 errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
608 struct_obj.* = .{737 struct_obj.* = .{
609 .owner_decl = sema.owner_decl,738 .owner_decl = new_decl,
610 .fields = fields_map,739 .fields = .{},
611 .node_offset = inst_data.src_node,740 .node_offset = src.node_offset,
612 .container = .{741 .zir_index = inst,
742 .layout = small.layout,
743 .status = .none,
744 .namespace = .{
745 .parent = sema.owner_decl.namespace,
613 .ty = struct_ty,746 .ty = struct_ty,
614 .file_scope = block.getFileScope(),747 .file_scope = block.getFileScope(),
615 .parent_name_hash = new_decl.fullyQualifiedNameHash(),
616 },748 },
617 };749 };
750 std.log.scoped(.module).debug("create struct {*} owned by {*} ({s})", .{
751 &struct_obj.namespace, new_decl, new_decl.name,
752 });
753 try sema.analyzeStructDecl(new_decl, inst, struct_obj);
754 try new_decl.finalizeNewArena(&new_decl_arena);
618 return sema.analyzeDeclVal(block, src, new_decl);755 return sema.analyzeDeclVal(block, src, new_decl);
619}756}
620757
758fn createTypeName(sema: *Sema, block: *Scope.Block, name_strategy: Zir.Inst.NameStrategy) ![:0]u8 {
759 switch (name_strategy) {
760 .anon => {
761 // It would be neat to have "struct:line:column" but this name has
762 // to survive incremental updates, where it may have been shifted down
763 // or up to a different line, but unchanged, and thus not unnecessarily
764 // semantically analyzed.
765 const name_index = sema.mod.getNextAnonNameIndex();
766 return std.fmt.allocPrintZ(sema.gpa, "{s}__anon_{d}", .{
767 sema.owner_decl.name, name_index,
768 });
769 },
770 .parent => return sema.gpa.dupeZ(u8, mem.spanZ(sema.owner_decl.name)),
771 .func => {
772 const name_index = sema.mod.getNextAnonNameIndex();
773 const name = try std.fmt.allocPrintZ(sema.gpa, "{s}__anon_{d}", .{
774 sema.owner_decl.name, name_index,
775 });
776 log.warn("TODO: handle NameStrategy.func correctly instead of using anon name '{s}'", .{
777 name,
778 });
779 return name;
780 },
781 }
782}
783
621fn zirEnumDecl(784fn zirEnumDecl(
622 sema: *Sema,785 sema: *Sema,
623 block: *Scope.Block,786 block: *Scope.Block,
624 inst: zir.Inst.Index,787 extended: Zir.Inst.Extended.InstData,
625 nonexhaustive: bool,
626) InnerError!*Inst {788) InnerError!*Inst {
627 const tracy = trace(@src());789 const tracy = trace(@src());
628 defer tracy.end();790 defer tracy.end();
629791
630 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;792 const mod = sema.mod;
631 const src = inst_data.src();793 const gpa = sema.gpa;
632 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);794 const small = @bitCast(Zir.Inst.EnumDecl.Small, extended.small);
795 var extra_index: usize = extended.operand;
796
797 const src: LazySrcLoc = if (small.has_src_node) blk: {
798 const node_offset = @bitCast(i32, sema.code.extra[extra_index]);
799 extra_index += 1;
800 break :blk .{ .node_offset = node_offset };
801 } else sema.src;
802
803 const tag_type_ref = if (small.has_tag_type) blk: {
804 const tag_type_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
805 extra_index += 1;
806 break :blk tag_type_ref;
807 } else .none;
808
809 const body_len = if (small.has_body_len) blk: {
810 const body_len = sema.code.extra[extra_index];
811 extra_index += 1;
812 break :blk body_len;
813 } else 0;
814
815 const fields_len = if (small.has_fields_len) blk: {
816 const fields_len = sema.code.extra[extra_index];
817 extra_index += 1;
818 break :blk fields_len;
819 } else 0;
820
821 const decls_len = if (small.has_decls_len) blk: {
822 const decls_len = sema.code.extra[extra_index];
823 extra_index += 1;
824 break :blk decls_len;
825 } else 0;
826
827 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
828 errdefer new_decl_arena.deinit();
829
830 const tag_ty = blk: {
831 if (tag_type_ref != .none) {
832 // TODO better source location
833 // TODO (needs AstGen fix too) move this eval to the block so it gets allocated
834 // in the new decl arena.
835 break :blk try sema.resolveType(block, src, tag_type_ref);
836 }
837 const bits = std.math.log2_int_ceil(usize, fields_len);
838 break :blk try Type.Tag.int_unsigned.create(&new_decl_arena.allocator, bits);
839 };
840
841 const enum_obj = try new_decl_arena.allocator.create(Module.EnumFull);
842 const enum_ty_payload = try new_decl_arena.allocator.create(Type.Payload.EnumFull);
843 enum_ty_payload.* = .{
844 .base = .{ .tag = if (small.nonexhaustive) .enum_nonexhaustive else .enum_full },
845 .data = enum_obj,
846 };
847 const enum_ty = Type.initPayload(&enum_ty_payload.base);
848 const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty);
849 const type_name = try sema.createTypeName(block, small.name_strategy);
850 const new_decl = try mod.createAnonymousDeclNamed(&block.base, .{
851 .ty = Type.initTag(.type),
852 .val = enum_val,
853 }, type_name);
854 errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
855
856 enum_obj.* = .{
857 .owner_decl = new_decl,
858 .tag_ty = tag_ty,
859 .fields = .{},
860 .values = .{},
861 .node_offset = src.node_offset,
862 .namespace = .{
863 .parent = sema.owner_decl.namespace,
864 .ty = enum_ty,
865 .file_scope = block.getFileScope(),
866 },
867 };
868 std.log.scoped(.module).debug("create enum {*} owned by {*} ({s})", .{
869 &enum_obj.namespace, new_decl, new_decl.name,
870 });
871
872 extra_index = try mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl);
873
874 const body = sema.code.extra[extra_index..][0..body_len];
875 if (fields_len == 0) {
876 assert(body.len == 0);
877 try new_decl.finalizeNewArena(&new_decl_arena);
878 return sema.analyzeDeclVal(block, src, new_decl);
879 }
880 extra_index += body.len;
881
882 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
883 const body_end = extra_index;
884 extra_index += bit_bags_count;
885
886 try enum_obj.fields.ensureCapacity(&new_decl_arena.allocator, fields_len);
887 const any_values = for (sema.code.extra[body_end..][0..bit_bags_count]) |bag| {
888 if (bag != 0) break true;
889 } else false;
890 if (any_values) {
891 try enum_obj.values.ensureCapacity(&new_decl_arena.allocator, fields_len);
892 }
893
894 {
895 // We create a block for the field type instructions because they
896 // may need to reference Decls from inside the enum namespace.
897 // Within the field type, default value, and alignment expressions, the "owner decl"
898 // should be the enum itself. Thus we need a new Sema.
899 var enum_sema: Sema = .{
900 .mod = mod,
901 .gpa = gpa,
902 .arena = &new_decl_arena.allocator,
903 .code = sema.code,
904 .inst_map = sema.inst_map,
905 .owner_decl = new_decl,
906 .namespace = &enum_obj.namespace,
907 .owner_func = null,
908 .func = null,
909 .param_inst_list = &.{},
910 .branch_quota = sema.branch_quota,
911 .branch_count = sema.branch_count,
912 };
913
914 var enum_block: Scope.Block = .{
915 .parent = null,
916 .sema = &enum_sema,
917 .src_decl = new_decl,
918 .instructions = .{},
919 .inlining = null,
920 .is_comptime = true,
921 };
922 defer assert(enum_block.instructions.items.len == 0); // should all be comptime instructions
923
924 if (body.len != 0) {
925 _ = try enum_sema.analyzeBody(&enum_block, body);
926 }
633927
634 return sema.mod.fail(&block.base, sema.src, "TODO implement zirEnumDecl", .{});928 sema.branch_count = enum_sema.branch_count;
929 sema.branch_quota = enum_sema.branch_quota;
930 }
931 var bit_bag_index: usize = body_end;
932 var cur_bit_bag: u32 = undefined;
933 var field_i: u32 = 0;
934 while (field_i < fields_len) : (field_i += 1) {
935 if (field_i % 32 == 0) {
936 cur_bit_bag = sema.code.extra[bit_bag_index];
937 bit_bag_index += 1;
938 }
939 const has_tag_value = @truncate(u1, cur_bit_bag) != 0;
940 cur_bit_bag >>= 1;
941
942 const field_name_zir = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
943 extra_index += 1;
944
945 // This string needs to outlive the ZIR code.
946 const field_name = try new_decl_arena.allocator.dupe(u8, field_name_zir);
947
948 const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name);
949 if (gop.found_existing) {
950 const tree = try sema.getAstTree(block);
951 const field_src = enumFieldSrcLoc(block.src_decl, tree.*, src.node_offset, field_i);
952 const other_tag_src = enumFieldSrcLoc(block.src_decl, tree.*, src.node_offset, gop.index);
953 const msg = msg: {
954 const msg = try mod.errMsg(&block.base, field_src, "duplicate enum tag", .{});
955 errdefer msg.destroy(gpa);
956 try mod.errNote(&block.base, other_tag_src, msg, "other tag here", .{});
957 break :msg msg;
958 };
959 return mod.failWithOwnedErrorMsg(&block.base, msg);
960 }
961
962 if (has_tag_value) {
963 const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
964 extra_index += 1;
965 // TODO: if we need to report an error here, use a source location
966 // that points to this default value expression rather than the struct.
967 // But only resolve the source location if we need to emit a compile error.
968 const tag_val = (try sema.resolveInstConst(block, src, tag_val_ref)).val;
969 enum_obj.values.putAssumeCapacityNoClobber(tag_val, {});
970 } else if (any_values) {
971 const tag_val = try Value.Tag.int_u64.create(&new_decl_arena.allocator, field_i);
972 enum_obj.values.putAssumeCapacityNoClobber(tag_val, {});
973 }
974 }
975
976 try new_decl.finalizeNewArena(&new_decl_arena);
977 return sema.analyzeDeclVal(block, src, new_decl);
978}
979
980fn zirUnionDecl(
981 sema: *Sema,
982 block: *Scope.Block,
983 extended: Zir.Inst.Extended.InstData,
984 inst: Zir.Inst.Index,
985) InnerError!*Inst {
986 const tracy = trace(@src());
987 defer tracy.end();
988
989 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);
990 var extra_index: usize = extended.operand;
991
992 const src: LazySrcLoc = if (small.has_src_node) blk: {
993 const node_offset = @bitCast(i32, sema.code.extra[extra_index]);
994 extra_index += 1;
995 break :blk .{ .node_offset = node_offset };
996 } else sema.src;
997
998 extra_index += @boolToInt(small.has_tag_type);
999 extra_index += @boolToInt(small.has_body_len);
1000 extra_index += @boolToInt(small.has_fields_len);
1001
1002 const decls_len = if (small.has_decls_len) blk: {
1003 const decls_len = sema.code.extra[extra_index];
1004 extra_index += 1;
1005 break :blk decls_len;
1006 } else 0;
1007
1008 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
1009 errdefer new_decl_arena.deinit();
1010
1011 const union_obj = try new_decl_arena.allocator.create(Module.Union);
1012 const union_ty = try Type.Tag.@"union".create(&new_decl_arena.allocator, union_obj);
1013 const union_val = try Value.Tag.ty.create(&new_decl_arena.allocator, union_ty);
1014 const type_name = try sema.createTypeName(block, small.name_strategy);
1015 const new_decl = try sema.mod.createAnonymousDeclNamed(&block.base, .{
1016 .ty = Type.initTag(.type),
1017 .val = union_val,
1018 }, type_name);
1019 errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
1020 union_obj.* = .{
1021 .owner_decl = new_decl,
1022 .tag_ty = Type.initTag(.@"null"),
1023 .fields = .{},
1024 .node_offset = src.node_offset,
1025 .zir_index = inst,
1026 .layout = small.layout,
1027 .status = .none,
1028 .namespace = .{
1029 .parent = sema.owner_decl.namespace,
1030 .ty = union_ty,
1031 .file_scope = block.getFileScope(),
1032 },
1033 };
1034 std.log.scoped(.module).debug("create union {*} owned by {*} ({s})", .{
1035 &union_obj.namespace, new_decl, new_decl.name,
1036 });
1037
1038 _ = try sema.mod.scanNamespace(&union_obj.namespace, extra_index, decls_len, new_decl);
1039
1040 try new_decl.finalizeNewArena(&new_decl_arena);
1041 return sema.analyzeDeclVal(block, src, new_decl);
635}1042}
6361043
637fn zirUnionDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1044fn zirOpaqueDecl(
1045 sema: *Sema,
1046 block: *Scope.Block,
1047 inst: Zir.Inst.Index,
1048 name_strategy: Zir.Inst.NameStrategy,
1049) InnerError!*Inst {
638 const tracy = trace(@src());1050 const tracy = trace(@src());
639 defer tracy.end();1051 defer tracy.end();
6401052
641 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;1053 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
642 const src = inst_data.src();1054 const src = inst_data.src();
643 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);1055 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
6441056
645 return sema.mod.fail(&block.base, sema.src, "TODO implement zirUnionDecl", .{});1057 return sema.mod.fail(&block.base, sema.src, "TODO implement zirOpaqueDecl", .{});
646}1058}
6471059
648fn zirOpaqueDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1060fn zirErrorSetDecl(
1061 sema: *Sema,
1062 block: *Scope.Block,
1063 inst: Zir.Inst.Index,
1064 name_strategy: Zir.Inst.NameStrategy,
1065) InnerError!*Inst {
649 const tracy = trace(@src());1066 const tracy = trace(@src());
650 defer tracy.end();1067 defer tracy.end();
6511068
1069 const gpa = sema.gpa;
652 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;1070 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
653 const src = inst_data.src();1071 const src = inst_data.src();
654 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);1072 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
1073 const fields = sema.code.extra[extra.end..][0..extra.data.fields_len];
6551074
656 return sema.mod.fail(&block.base, sema.src, "TODO implement zirOpaqueDecl", .{});1075 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
1076 errdefer new_decl_arena.deinit();
1077
1078 const error_set = try new_decl_arena.allocator.create(Module.ErrorSet);
1079 const error_set_ty = try Type.Tag.error_set.create(&new_decl_arena.allocator, error_set);
1080 const error_set_val = try Value.Tag.ty.create(&new_decl_arena.allocator, error_set_ty);
1081 const type_name = try sema.createTypeName(block, name_strategy);
1082 const new_decl = try sema.mod.createAnonymousDeclNamed(&block.base, .{
1083 .ty = Type.initTag(.type),
1084 .val = error_set_val,
1085 }, type_name);
1086 errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
1087 const names = try new_decl_arena.allocator.alloc([]const u8, fields.len);
1088 for (fields) |str_index, i| {
1089 names[i] = try new_decl_arena.allocator.dupe(u8, sema.code.nullTerminatedString(str_index));
1090 }
1091 error_set.* = .{
1092 .owner_decl = new_decl,
1093 .node_offset = inst_data.src_node,
1094 .names_ptr = names.ptr,
1095 .names_len = @intCast(u32, names.len),
1096 };
1097 try new_decl.finalizeNewArena(&new_decl_arena);
1098 return sema.analyzeDeclVal(block, src, new_decl);
657}1099}
6581100
659fn zirRetPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1101fn zirRetPtr(
1102 sema: *Sema,
1103 block: *Scope.Block,
1104 extended: Zir.Inst.Extended.InstData,
1105) InnerError!*Inst {
660 const tracy = trace(@src());1106 const tracy = trace(@src());
661 defer tracy.end();1107 defer tracy.end();
6621108
663 const src: LazySrcLoc = .unneeded;1109 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
664 try sema.requireFunctionBlock(block, src);1110 try sema.requireFunctionBlock(block, src);
665 const fn_ty = sema.func.?.owner_decl.typed_value.most_recent.typed_value.ty;1111 const fn_ty = sema.func.?.owner_decl.ty;
666 const ret_type = fn_ty.fnReturnType();1112 const ret_type = fn_ty.fnReturnType();
667 const ptr_type = try sema.mod.simplePtrType(sema.arena, ret_type, true, .One);1113 const ptr_type = try sema.mod.simplePtrType(sema.arena, ret_type, true, .One);
668 return block.addNoOp(src, ptr_type, .alloc);1114 return block.addNoOp(src, ptr_type, .alloc);
669}1115}
6701116
671fn zirRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1117fn zirRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
672 const tracy = trace(@src());1118 const tracy = trace(@src());
673 defer tracy.end();1119 defer tracy.end();
6741120
...@@ -677,18 +1123,22 @@ fn zirRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In...@@ -677,18 +1123,22 @@ fn zirRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In
677 return sema.analyzeRef(block, inst_data.src(), operand);1123 return sema.analyzeRef(block, inst_data.src(), operand);
678}1124}
6791125
680fn zirRetType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1126fn zirRetType(
1127 sema: *Sema,
1128 block: *Scope.Block,
1129 extended: Zir.Inst.Extended.InstData,
1130) InnerError!*Inst {
681 const tracy = trace(@src());1131 const tracy = trace(@src());
682 defer tracy.end();1132 defer tracy.end();
6831133
684 const src: LazySrcLoc = .unneeded;1134 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
685 try sema.requireFunctionBlock(block, src);1135 try sema.requireFunctionBlock(block, src);
686 const fn_ty = sema.func.?.owner_decl.typed_value.most_recent.typed_value.ty;1136 const fn_ty = sema.func.?.owner_decl.ty;
687 const ret_type = fn_ty.fnReturnType();1137 const ret_type = fn_ty.fnReturnType();
688 return sema.mod.constType(sema.arena, src, ret_type);1138 return sema.mod.constType(sema.arena, src, ret_type);
689}1139}
6901140
691fn zirEnsureResultUsed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1141fn zirEnsureResultUsed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
692 const tracy = trace(@src());1142 const tracy = trace(@src());
693 defer tracy.end();1143 defer tracy.end();
6941144
...@@ -711,7 +1161,7 @@ fn ensureResultUsed(...@@ -711,7 +1161,7 @@ fn ensureResultUsed(
711 }1161 }
712}1162}
7131163
714fn zirEnsureResultNonError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1164fn zirEnsureResultNonError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
715 const tracy = trace(@src());1165 const tracy = trace(@src());
716 defer tracy.end();1166 defer tracy.end();
7171167
...@@ -724,7 +1174,7 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Inde...@@ -724,7 +1174,7 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Inde
724 }1174 }
725}1175}
7261176
727fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1177fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
728 const tracy = trace(@src());1178 const tracy = trace(@src());
729 defer tracy.end();1179 defer tracy.end();
7301180
...@@ -758,7 +1208,48 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In...@@ -758,7 +1208,48 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In
758 return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);1208 return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);
759}1209}
7601210
761fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1211fn zirArg(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1212 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
1213 const src = inst_data.src();
1214 const arg_name = inst_data.get(sema.code);
1215 const arg_index = sema.next_arg_index;
1216 sema.next_arg_index += 1;
1217
1218 // TODO check if arg_name shadows a Decl
1219
1220 if (block.inlining) |inlining| {
1221 return sema.param_inst_list[arg_index];
1222 }
1223
1224 // Need to set the name of the Air.Arg instruction.
1225 const air_arg = sema.param_inst_list[arg_index].castTag(.arg).?;
1226 air_arg.name = arg_name;
1227 return &air_arg.base;
1228}
1229
1230fn zirAllocExtended(
1231 sema: *Sema,
1232 block: *Scope.Block,
1233 extended: Zir.Inst.Extended.InstData,
1234) InnerError!*Inst {
1235 const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand);
1236 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
1237 return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocExtended", .{});
1238}
1239
1240fn zirAllocComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1241 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1242 const src = inst_data.src();
1243 return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocComptime", .{});
1244}
1245
1246fn zirAllocInferredComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1247 const src_node = sema.code.instructions.items(.data)[inst].node;
1248 const src: LazySrcLoc = .{ .node_offset = src_node };
1249 return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocInferredComptime", .{});
1250}
1251
1252fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
762 const tracy = trace(@src());1253 const tracy = trace(@src());
763 defer tracy.end();1254 defer tracy.end();
7641255
...@@ -771,7 +1262,7 @@ fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*...@@ -771,7 +1262,7 @@ fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*
771 return block.addNoOp(var_decl_src, ptr_type, .alloc);1262 return block.addNoOp(var_decl_src, ptr_type, .alloc);
772}1263}
7731264
774fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1265fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
775 const tracy = trace(@src());1266 const tracy = trace(@src());
776 defer tracy.end();1267 defer tracy.end();
7771268
...@@ -788,7 +1279,7 @@ fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro...@@ -788,7 +1279,7 @@ fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
788fn zirAllocInferred(1279fn zirAllocInferred(
789 sema: *Sema,1280 sema: *Sema,
790 block: *Scope.Block,1281 block: *Scope.Block,
791 inst: zir.Inst.Index,1282 inst: Zir.Inst.Index,
792 inferred_alloc_ty: Type,1283 inferred_alloc_ty: Type,
793) InnerError!*Inst {1284) InnerError!*Inst {
794 const tracy = trace(@src());1285 const tracy = trace(@src());
...@@ -814,7 +1305,7 @@ fn zirAllocInferred(...@@ -814,7 +1305,7 @@ fn zirAllocInferred(
814 return result;1305 return result;
815}1306}
8161307
817fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1308fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
818 const tracy = trace(@src());1309 const tracy = trace(@src());
819 defer tracy.end();1310 defer tracy.end();
8201311
...@@ -840,7 +1331,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Inde...@@ -840,7 +1331,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Inde
840 ptr.tag = .alloc;1331 ptr.tag = .alloc;
841}1332}
8421333
843fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1334fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
844 const tracy = trace(@src());1335 const tracy = trace(@src());
845 defer tracy.end();1336 defer tracy.end();
8461337
...@@ -848,26 +1339,25 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Ind...@@ -848,26 +1339,25 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Ind
848 const mod = sema.mod;1339 const mod = sema.mod;
849 const validate_inst = sema.code.instructions.items(.data)[inst].pl_node;1340 const validate_inst = sema.code.instructions.items(.data)[inst].pl_node;
850 const struct_init_src = validate_inst.src();1341 const struct_init_src = validate_inst.src();
851 const validate_extra = sema.code.extraData(zir.Inst.Block, validate_inst.payload_index);1342 const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index);
852 const instrs = sema.code.extra[validate_extra.end..][0..validate_extra.data.body_len];1343 const instrs = sema.code.extra[validate_extra.end..][0..validate_extra.data.body_len];
8531344
854 const struct_obj: *Module.Struct = s: {1345 const struct_obj: *Module.Struct = s: {
855 const field_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;1346 const field_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;
856 const field_ptr_extra = sema.code.extraData(zir.Inst.Field, field_ptr_data.payload_index).data;1347 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
857 const object_ptr = try sema.resolveInst(field_ptr_extra.lhs);1348 const object_ptr = try sema.resolveInst(field_ptr_extra.lhs);
858 break :s object_ptr.ty.elemType().castTag(.@"struct").?.data;1349 break :s object_ptr.ty.elemType().castTag(.@"struct").?.data;
859 };1350 };
8601351
861 // Maps field index to field_ptr index of where it was already initialized.1352 // Maps field index to field_ptr index of where it was already initialized.
862 const found_fields = try gpa.alloc(zir.Inst.Index, struct_obj.fields.entries.items.len);1353 const found_fields = try gpa.alloc(Zir.Inst.Index, struct_obj.fields.entries.items.len);
863 defer gpa.free(found_fields);1354 defer gpa.free(found_fields);
8641355 mem.set(Zir.Inst.Index, found_fields, 0);
865 mem.set(zir.Inst.Index, found_fields, 0);
8661356
867 for (instrs) |field_ptr| {1357 for (instrs) |field_ptr| {
868 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;1358 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;
869 const field_src: LazySrcLoc = .{ .node_offset_back2tok = field_ptr_data.src_node };1359 const field_src: LazySrcLoc = .{ .node_offset_back2tok = field_ptr_data.src_node };
870 const field_ptr_extra = sema.code.extraData(zir.Inst.Field, field_ptr_data.payload_index).data;1360 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
871 const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start);1361 const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start);
872 const field_index = struct_obj.fields.getIndex(field_name) orelse1362 const field_index = struct_obj.fields.getIndex(field_name) orelse
873 return sema.failWithBadFieldAccess(block, struct_obj, field_src, field_name);1363 return sema.failWithBadFieldAccess(block, struct_obj, field_src, field_name);
...@@ -888,11 +1378,12 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Ind...@@ -888,11 +1378,12 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Ind
8881378
889 var root_msg: ?*Module.ErrorMsg = null;1379 var root_msg: ?*Module.ErrorMsg = null;
8901380
1381 // TODO handle default struct field values
891 for (found_fields) |field_ptr, i| {1382 for (found_fields) |field_ptr, i| {
892 if (field_ptr != 0) continue;1383 if (field_ptr != 0) continue;
8931384
894 const field_name = struct_obj.fields.entries.items[i].key;1385 const field_name = struct_obj.fields.entries.items[i].key;
895 const template = "mising struct field: {s}";1386 const template = "missing struct field: {s}";
896 const args = .{field_name};1387 const args = .{field_name};
897 if (root_msg) |msg| {1388 if (root_msg) |msg| {
898 try mod.errNote(&block.base, struct_init_src, msg, template, args);1389 try mod.errNote(&block.base, struct_init_src, msg, template, args);
...@@ -913,6 +1404,12 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Ind...@@ -913,6 +1404,12 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Ind
913 }1404 }
914}1405}
9151406
1407fn zirValidateArrayInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
1408 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1409 const src = inst_data.src();
1410 return sema.mod.fail(&block.base, src, "TODO implement Sema.zirValidateArrayInitPtr", .{});
1411}
1412
916fn failWithBadFieldAccess(1413fn failWithBadFieldAccess(
917 sema: *Sema,1414 sema: *Sema,
918 block: *Scope.Block,1415 block: *Scope.Block,
...@@ -940,11 +1437,43 @@ fn failWithBadFieldAccess(...@@ -940,11 +1437,43 @@ fn failWithBadFieldAccess(
940 return mod.failWithOwnedErrorMsg(&block.base, msg);1437 return mod.failWithOwnedErrorMsg(&block.base, msg);
941}1438}
9421439
943fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1440fn failWithBadUnionFieldAccess(
1441 sema: *Sema,
1442 block: *Scope.Block,
1443 union_obj: *Module.Union,
1444 field_src: LazySrcLoc,
1445 field_name: []const u8,
1446) InnerError {
1447 const mod = sema.mod;
1448 const gpa = sema.gpa;
1449
1450 const fqn = try union_obj.getFullyQualifiedName(gpa);
1451 defer gpa.free(fqn);
1452
1453 const msg = msg: {
1454 const msg = try mod.errMsg(
1455 &block.base,
1456 field_src,
1457 "no field named '{s}' in union '{s}'",
1458 .{ field_name, fqn },
1459 );
1460 errdefer msg.destroy(gpa);
1461 try mod.errNoteNonLazy(union_obj.srcLoc(), msg, "union declared here", .{});
1462 break :msg msg;
1463 };
1464 return mod.failWithOwnedErrorMsg(&block.base, msg);
1465}
1466
1467fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
944 const tracy = trace(@src());1468 const tracy = trace(@src());
945 defer tracy.end();1469 defer tracy.end();
9461470
947 const bin_inst = sema.code.instructions.items(.data)[inst].bin;1471 const bin_inst = sema.code.instructions.items(.data)[inst].bin;
1472 if (bin_inst.lhs == .none) {
1473 // This is an elided instruction, but AstGen was not smart enough
1474 // to omit it.
1475 return;
1476 }
948 const ptr = try sema.resolveInst(bin_inst.lhs);1477 const ptr = try sema.resolveInst(bin_inst.lhs);
949 const value = try sema.resolveInst(bin_inst.rhs);1478 const value = try sema.resolveInst(bin_inst.rhs);
950 const ptr_ty = try sema.mod.simplePtrType(sema.arena, value.ty, true, .One);1479 const ptr_ty = try sema.mod.simplePtrType(sema.arena, value.ty, true, .One);
...@@ -956,7 +1485,7 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In...@@ -956,7 +1485,7 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In
956 return sema.storePtr(block, src, bitcasted_ptr, value);1485 return sema.storePtr(block, src, bitcasted_ptr, value);
957}1486}
9581487
959fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1488fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
960 const tracy = trace(@src());1489 const tracy = trace(@src());
961 defer tracy.end();1490 defer tracy.end();
9621491
...@@ -975,16 +1504,15 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index)...@@ -975,16 +1504,15 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index)
975 return sema.storePtr(block, src, bitcasted_ptr, value);1504 return sema.storePtr(block, src, bitcasted_ptr, value);
976}1505}
9771506
978fn zirSetEvalBranchQuota(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1507fn zirSetEvalBranchQuota(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
979 const inst_data = sema.code.instructions.items(.data)[inst].un_node;1508 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
980 const src = inst_data.src();1509 const src = inst_data.src();
981 try sema.requireFunctionBlock(block, src);
982 const quota = try sema.resolveAlreadyCoercedInt(block, src, inst_data.operand, u32);1510 const quota = try sema.resolveAlreadyCoercedInt(block, src, inst_data.operand, u32);
983 if (sema.branch_quota < quota)1511 if (sema.branch_quota < quota)
984 sema.branch_quota = quota;1512 sema.branch_quota = quota;
985}1513}
9861514
987fn zirStore(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1515fn zirStore(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
988 const tracy = trace(@src());1516 const tracy = trace(@src());
989 defer tracy.end();1517 defer tracy.end();
9901518
...@@ -994,19 +1522,19 @@ fn zirStore(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!v...@@ -994,19 +1522,19 @@ fn zirStore(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!v
994 return sema.storePtr(block, sema.src, ptr, value);1522 return sema.storePtr(block, sema.src, ptr, value);
995}1523}
9961524
997fn zirStoreNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1525fn zirStoreNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
998 const tracy = trace(@src());1526 const tracy = trace(@src());
999 defer tracy.end();1527 defer tracy.end();
10001528
1001 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;1529 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1002 const src = inst_data.src();1530 const src = inst_data.src();
1003 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;1531 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1004 const ptr = try sema.resolveInst(extra.lhs);1532 const ptr = try sema.resolveInst(extra.lhs);
1005 const value = try sema.resolveInst(extra.rhs);1533 const value = try sema.resolveInst(extra.rhs);
1006 return sema.storePtr(block, src, ptr, value);1534 return sema.storePtr(block, src, ptr, value);
1007}1535}
10081536
1009fn zirParamType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1537fn zirParamType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1010 const tracy = trace(@src());1538 const tracy = trace(@src());
1011 defer tracy.end();1539 defer tracy.end();
10121540
...@@ -1042,7 +1570,7 @@ fn zirParamType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr...@@ -1042,7 +1570,7 @@ fn zirParamType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
1042 return sema.mod.constType(sema.arena, src, param_type);1570 return sema.mod.constType(sema.arena, src, param_type);
1043}1571}
10441572
1045fn zirStr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1573fn zirStr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1046 const tracy = trace(@src());1574 const tracy = trace(@src());
1047 defer tracy.end();1575 defer tracy.end();
10481576
...@@ -1061,14 +1589,16 @@ fn zirStr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In...@@ -1061,14 +1589,16 @@ fn zirStr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In
1061 const decl_ty = try Type.Tag.array_u8_sentinel_0.create(&new_decl_arena.allocator, bytes.len);1589 const decl_ty = try Type.Tag.array_u8_sentinel_0.create(&new_decl_arena.allocator, bytes.len);
1062 const decl_val = try Value.Tag.bytes.create(&new_decl_arena.allocator, bytes);1590 const decl_val = try Value.Tag.bytes.create(&new_decl_arena.allocator, bytes);
10631591
1064 const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{1592 const new_decl = try sema.mod.createAnonymousDecl(&block.base, .{
1065 .ty = decl_ty,1593 .ty = decl_ty,
1066 .val = decl_val,1594 .val = decl_val,
1067 });1595 });
1596 errdefer sema.mod.deleteAnonDecl(&block.base, new_decl);
1597 try new_decl.finalizeNewArena(&new_decl_arena);
1068 return sema.analyzeDeclRef(block, .unneeded, new_decl);1598 return sema.analyzeDeclRef(block, .unneeded, new_decl);
1069}1599}
10701600
1071fn zirInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1601fn zirInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1072 const tracy = trace(@src());1602 const tracy = trace(@src());
1073 defer tracy.end();1603 defer tracy.end();
10741604
...@@ -1076,11 +1606,28 @@ fn zirInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In...@@ -1076,11 +1606,28 @@ fn zirInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In
1076 return sema.mod.constIntUnsigned(sema.arena, .unneeded, Type.initTag(.comptime_int), int);1606 return sema.mod.constIntUnsigned(sema.arena, .unneeded, Type.initTag(.comptime_int), int);
1077}1607}
10781608
1079fn zirFloat(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1609fn zirIntBig(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1080 const arena = sema.arena;1610 const tracy = trace(@src());
1081 const inst_data = sema.code.instructions.items(.data)[inst].float;1611 defer tracy.end();
1082 const src = inst_data.src();1612
1083 const number = inst_data.number;1613 const arena = sema.arena;
1614 const int = sema.code.instructions.items(.data)[inst].str;
1615 const byte_count = int.len * @sizeOf(std.math.big.Limb);
1616 const limb_bytes = sema.code.string_bytes[int.start..][0..byte_count];
1617 const limbs = try arena.alloc(std.math.big.Limb, int.len);
1618 mem.copy(u8, mem.sliceAsBytes(limbs), limb_bytes);
1619
1620 return sema.mod.constInst(arena, .unneeded, .{
1621 .ty = Type.initTag(.comptime_int),
1622 .val = try Value.Tag.int_big_positive.create(arena, limbs),
1623 });
1624}
1625
1626fn zirFloat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1627 const arena = sema.arena;
1628 const inst_data = sema.code.instructions.items(.data)[inst].float;
1629 const src = inst_data.src();
1630 const number = inst_data.number;
10841631
1085 return sema.mod.constInst(arena, src, .{1632 return sema.mod.constInst(arena, src, .{
1086 .ty = Type.initTag(.comptime_float),1633 .ty = Type.initTag(.comptime_float),
...@@ -1088,10 +1635,10 @@ fn zirFloat(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*...@@ -1088,10 +1635,10 @@ fn zirFloat(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*
1088 });1635 });
1089}1636}
10901637
1091fn zirFloat128(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1638fn zirFloat128(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1092 const arena = sema.arena;1639 const arena = sema.arena;
1093 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;1640 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1094 const extra = sema.code.extraData(zir.Inst.Float128, inst_data.payload_index).data;1641 const extra = sema.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data;
1095 const src = inst_data.src();1642 const src = inst_data.src();
1096 const number = extra.get();1643 const number = extra.get();
10971644
...@@ -1101,7 +1648,7 @@ fn zirFloat128(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro...@@ -1101,7 +1648,7 @@ fn zirFloat128(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
1101 });1648 });
1102}1649}
11031650
1104fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {1651fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Zir.Inst.Index {
1105 const tracy = trace(@src());1652 const tracy = trace(@src());
1106 defer tracy.end();1653 defer tracy.end();
11071654
...@@ -1112,20 +1659,25 @@ fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inner...@@ -1112,20 +1659,25 @@ fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inner
1112 return sema.mod.fail(&block.base, src, "{s}", .{msg});1659 return sema.mod.fail(&block.base, src, "{s}", .{msg});
1113}1660}
11141661
1115fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1662fn zirCompileLog(
1663 sema: *Sema,
1664 block: *Scope.Block,
1665 extended: Zir.Inst.Extended.InstData,
1666) InnerError!*Inst {
1116 var managed = sema.mod.compile_log_text.toManaged(sema.gpa);1667 var managed = sema.mod.compile_log_text.toManaged(sema.gpa);
1117 defer sema.mod.compile_log_text = managed.moveToUnmanaged();1668 defer sema.mod.compile_log_text = managed.moveToUnmanaged();
1118 const writer = managed.writer();1669 const writer = managed.writer();
11191670
1120 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;1671 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
1121 const extra = sema.code.extraData(zir.Inst.MultiOp, inst_data.payload_index);1672 const src_node = extra.data.src_node;
1122 const args = sema.code.refSlice(extra.end, extra.data.operands_len);1673 const src: LazySrcLoc = .{ .node_offset = src_node };
1674 const args = sema.code.refSlice(extra.end, extended.small);
11231675
1124 for (args) |arg_ref, i| {1676 for (args) |arg_ref, i| {
1125 if (i != 0) try writer.print(", ", .{});1677 if (i != 0) try writer.print(", ", .{});
11261678
1127 const arg = try sema.resolveInst(arg_ref);1679 const arg = try sema.resolveInst(arg_ref);
1128 if (arg.value()) |val| {1680 if (try sema.resolvePossiblyUndefinedValue(block, src, arg)) |val| {
1129 try writer.print("@as({}, {})", .{ arg.ty, val });1681 try writer.print("@as({}, {})", .{ arg.ty, val });
1130 } else {1682 } else {
1131 try writer.print("@as({}, [runtime value])", .{arg.ty});1683 try writer.print("@as({}, [runtime value])", .{arg.ty});
...@@ -1135,11 +1687,15 @@ fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr...@@ -1135,11 +1687,15 @@ fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
11351687
1136 const gop = try sema.mod.compile_log_decls.getOrPut(sema.gpa, sema.owner_decl);1688 const gop = try sema.mod.compile_log_decls.getOrPut(sema.gpa, sema.owner_decl);
1137 if (!gop.found_existing) {1689 if (!gop.found_existing) {
1138 gop.entry.value = inst_data.src().toSrcLoc(&block.base);1690 gop.entry.value = src_node;
1139 }1691 }
1692 return sema.mod.constInst(sema.arena, src, .{
1693 .ty = Type.initTag(.void),
1694 .val = Value.initTag(.void_value),
1695 });
1140}1696}
11411697
1142fn zirRepeat(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {1698fn zirRepeat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Zir.Inst.Index {
1143 const tracy = trace(@src());1699 const tracy = trace(@src());
1144 defer tracy.end();1700 defer tracy.end();
11451701
...@@ -1149,16 +1705,23 @@ fn zirRepeat(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!...@@ -1149,16 +1705,23 @@ fn zirRepeat(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!
1149 return always_noreturn;1705 return always_noreturn;
1150}1706}
11511707
1152fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1708fn zirPanic(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Zir.Inst.Index {
1709 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1710 const src: LazySrcLoc = inst_data.src();
1711 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirPanic", .{});
1712 //return always_noreturn;
1713}
1714
1715fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1153 const tracy = trace(@src());1716 const tracy = trace(@src());
1154 defer tracy.end();1717 defer tracy.end();
11551718
1156 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;1719 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1157 const src = inst_data.src();1720 const src = inst_data.src();
1158 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);1721 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
1159 const body = sema.code.extra[extra.end..][0..extra.data.body_len];1722 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
11601723
1161 // TZIR expects a block outside the loop block too.1724 // AIR expects a block outside the loop block too.
1162 const block_inst = try sema.arena.create(Inst.Block);1725 const block_inst = try sema.arena.create(Inst.Block);
1163 block_inst.* = .{1726 block_inst.* = .{
1164 .base = .{1727 .base = .{
...@@ -1169,8 +1732,7 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerE...@@ -1169,8 +1732,7 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerE
1169 .body = undefined,1732 .body = undefined,
1170 };1733 };
11711734
1172 var child_block = parent_block.makeSubBlock();1735 var label: Scope.Block.Label = .{
1173 child_block.label = Scope.Block.Label{
1174 .zir_block = inst,1736 .zir_block = inst,
1175 .merges = .{1737 .merges = .{
1176 .results = .{},1738 .results = .{},
...@@ -1178,6 +1740,8 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerE...@@ -1178,6 +1740,8 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerE
1178 .block_inst = block_inst,1740 .block_inst = block_inst,
1179 },1741 },
1180 };1742 };
1743 var child_block = parent_block.makeSubBlock();
1744 child_block.label = &label;
1181 const merges = &child_block.label.?.merges;1745 const merges = &child_block.label.?.merges;
11821746
1183 defer child_block.instructions.deinit(sema.gpa);1747 defer child_block.instructions.deinit(sema.gpa);
...@@ -1210,13 +1774,29 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerE...@@ -1210,13 +1774,29 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerE
1210 return sema.analyzeBlockBody(parent_block, src, &child_block, merges);1774 return sema.analyzeBlockBody(parent_block, src, &child_block, merges);
1211}1775}
12121776
1213fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1777fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1778 const tracy = trace(@src());
1779 defer tracy.end();
1780
1781 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1782 const src = inst_data.src();
1783
1784 return sema.mod.fail(&parent_block.base, src, "TODO: implement Sema.zirCImport", .{});
1785}
1786
1787fn zirSuspendBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1788 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1789 const src = inst_data.src();
1790 return sema.mod.fail(&parent_block.base, src, "TODO: implement Sema.zirSuspendBlock", .{});
1791}
1792
1793fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1214 const tracy = trace(@src());1794 const tracy = trace(@src());
1215 defer tracy.end();1795 defer tracy.end();
12161796
1217 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;1797 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1218 const src = inst_data.src();1798 const src = inst_data.src();
1219 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);1799 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
1220 const body = sema.code.extra[extra.end..][0..extra.data.body_len];1800 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
12211801
1222 // Reserve space for a Block instruction so that generated Break instructions can1802 // Reserve space for a Block instruction so that generated Break instructions can
...@@ -1232,20 +1812,21 @@ fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) Inner...@@ -1232,20 +1812,21 @@ fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) Inner
1232 .body = undefined,1812 .body = undefined,
1233 };1813 };
12341814
1815 var label: Scope.Block.Label = .{
1816 .zir_block = inst,
1817 .merges = .{
1818 .results = .{},
1819 .br_list = .{},
1820 .block_inst = block_inst,
1821 },
1822 };
1823
1235 var child_block: Scope.Block = .{1824 var child_block: Scope.Block = .{
1236 .parent = parent_block,1825 .parent = parent_block,
1237 .sema = sema,1826 .sema = sema,
1238 .src_decl = parent_block.src_decl,1827 .src_decl = parent_block.src_decl,
1239 .instructions = .{},1828 .instructions = .{},
1240 // TODO @as here is working around a stage1 miscompilation bug :(1829 .label = &label,
1241 .label = @as(?Scope.Block.Label, Scope.Block.Label{
1242 .zir_block = inst,
1243 .merges = .{
1244 .results = .{},
1245 .br_list = .{},
1246 .block_inst = block_inst,
1247 },
1248 }),
1249 .inlining = parent_block.inlining,1830 .inlining = parent_block.inlining,
1250 .is_comptime = parent_block.is_comptime,1831 .is_comptime = parent_block.is_comptime,
1251 };1832 };
...@@ -1260,6 +1841,18 @@ fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) Inner...@@ -1260,6 +1841,18 @@ fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) Inner
1260 return sema.analyzeBlockBody(parent_block, src, &child_block, merges);1841 return sema.analyzeBlockBody(parent_block, src, &child_block, merges);
1261}1842}
12621843
1844fn resolveBlockBody(
1845 sema: *Sema,
1846 parent_block: *Scope.Block,
1847 src: LazySrcLoc,
1848 child_block: *Scope.Block,
1849 body: []const Zir.Inst.Index,
1850 merges: *Scope.Block.Merges,
1851) InnerError!*Inst {
1852 _ = try sema.analyzeBody(child_block, body);
1853 return sema.analyzeBlockBody(parent_block, src, child_block, merges);
1854}
1855
1263fn analyzeBlockBody(1856fn analyzeBlockBody(
1264 sema: *Sema,1857 sema: *Sema,
1265 parent_block: *Scope.Block,1858 parent_block: *Scope.Block,
...@@ -1342,29 +1935,64 @@ fn analyzeBlockBody(...@@ -1342,29 +1935,64 @@ fn analyzeBlockBody(
1342 return &merges.block_inst.base;1935 return &merges.block_inst.base;
1343}1936}
13441937
1345fn zirExport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1938fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
1346 const tracy = trace(@src());1939 const tracy = trace(@src());
1347 defer tracy.end();1940 defer tracy.end();
13481941
1349 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;1942 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1350 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;1943 const extra = sema.code.extraData(Zir.Inst.Export, inst_data.payload_index).data;
1351 const src = inst_data.src();1944 const src = inst_data.src();
1352 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };1945 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1353 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };1946 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
1947 const decl_name = sema.code.nullTerminatedString(extra.decl_name);
1948 const decl = try sema.lookupIdentifier(block, lhs_src, decl_name);
1949 const options = try sema.resolveInstConst(block, rhs_src, extra.options);
1950 const struct_obj = options.ty.castTag(.@"struct").?.data;
1951 const fields = options.val.castTag(.@"struct").?.data[0..struct_obj.fields.count()];
1952 const name_index = struct_obj.fields.getIndex("name").?;
1953 const linkage_index = struct_obj.fields.getIndex("linkage").?;
1954 const section_index = struct_obj.fields.getIndex("section").?;
1955 const export_name = try fields[name_index].toAllocatedBytes(sema.arena);
1956 const linkage = fields[linkage_index].toEnum(
1957 struct_obj.fields.items()[linkage_index].value.ty,
1958 std.builtin.GlobalLinkage,
1959 );
1960
1961 if (linkage != .Strong) {
1962 return sema.mod.fail(&block.base, src, "TODO: implement exporting with non-strong linkage", .{});
1963 }
1964 if (!fields[section_index].isNull()) {
1965 return sema.mod.fail(&block.base, src, "TODO: implement exporting with linksection", .{});
1966 }
1967
1968 try sema.mod.analyzeExport(&block.base, src, export_name, decl);
1969}
1970
1971fn zirSetAlignStack(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
1972 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1973 const src: LazySrcLoc = inst_data.src();
1974 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirSetAlignStack", .{});
1975}
1976
1977fn zirSetCold(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
1978 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1979 const src: LazySrcLoc = inst_data.src();
1980 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirSetCold", .{});
1981}
13541982
1355 // TODO (see corresponding TODO in AstGen) this is supposed to be a `decl_ref`1983fn zirSetFloatMode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
1356 // instruction, which could reference any decl, which is then supposed to get1984 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1357 // exported, regardless of whether or not it is a function.1985 const src: LazySrcLoc = inst_data.src();
1358 const target_fn = try sema.resolveInstConst(block, lhs_src, extra.lhs);1986 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirSetFloatMode", .{});
1359 // TODO (see corresponding TODO in AstGen) this is supposed to be1987}
1360 // `std.builtin.ExportOptions`, not a string.
1361 const export_name = try sema.resolveConstString(block, rhs_src, extra.rhs);
13621988
1363 const actual_fn = target_fn.val.castTag(.function).?.data;1989fn zirSetRuntimeSafety(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
1364 try sema.mod.analyzeExport(&block.base, src, export_name, actual_fn.owner_decl);1990 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1991 const src: LazySrcLoc = inst_data.src();
1992 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirSetRuntimeSafety", .{});
1365}1993}
13661994
1367fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {1995fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
1368 const tracy = trace(@src());1996 const tracy = trace(@src());
1369 defer tracy.end();1997 defer tracy.end();
13701998
...@@ -1374,7 +2002,13 @@ fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr...@@ -1374,7 +2002,13 @@ fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
1374 _ = try block.addNoOp(src, Type.initTag(.void), .breakpoint);2002 _ = try block.addNoOp(src, Type.initTag(.void), .breakpoint);
1375}2003}
13762004
1377fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {2005fn zirFence(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
2006 const src_node = sema.code.instructions.items(.data)[inst].node;
2007 const src: LazySrcLoc = .{ .node_offset = src_node };
2008 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirFence", .{});
2009}
2010
2011fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Zir.Inst.Index {
1378 const tracy = trace(@src());2012 const tracy = trace(@src());
1379 defer tracy.end();2013 defer tracy.end();
13802014
...@@ -1385,7 +2019,7 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: zir.Inst.Index) InnerE...@@ -1385,7 +2019,7 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: zir.Inst.Index) InnerE
13852019
1386 var block = start_block;2020 var block = start_block;
1387 while (true) {2021 while (true) {
1388 if (block.label) |*label| {2022 if (block.label) |label| {
1389 if (label.zir_block == zir_block) {2023 if (label.zir_block == zir_block) {
1390 // Here we add a br instruction, but we over-allocate a little bit2024 // Here we add a br instruction, but we over-allocate a little bit
1391 // (if necessary) to make it possible to convert the instruction into2025 // (if necessary) to make it possible to convert the instruction into
...@@ -1414,7 +2048,7 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: zir.Inst.Index) InnerE...@@ -1414,7 +2048,7 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: zir.Inst.Index) InnerE
1414 }2048 }
1415}2049}
14162050
1417fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {2051fn zirDbgStmt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
1418 const tracy = trace(@src());2052 const tracy = trace(@src());
1419 defer tracy.end();2053 defer tracy.end();
14202054
...@@ -1424,47 +2058,70 @@ fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE...@@ -1424,47 +2058,70 @@ fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE
1424 // instructions.2058 // instructions.
1425 if (block.is_comptime) return;2059 if (block.is_comptime) return;
14262060
1427 const src_node = sema.code.instructions.items(.data)[inst].node;2061 const inst_data = sema.code.instructions.items(.data)[inst].dbg_stmt;
1428 const src: LazySrcLoc = .{ .node_offset = src_node };2062 _ = try block.addDbgStmt(.unneeded, inst_data.line, inst_data.column);
1429
1430 const src_loc = src.toSrcLoc(&block.base);
1431 const abs_byte_off = try src_loc.byteOffset();
1432 _ = try block.addDbgStmt(src, abs_byte_off);
1433}2063}
14342064
1435fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2065fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1436 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;2066 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
1437 const src = inst_data.src();2067 const src = inst_data.src();
1438 const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key;2068 const decl_name = inst_data.get(sema.code);
2069 const decl = try sema.lookupIdentifier(block, src, decl_name);
1439 return sema.analyzeDeclRef(block, src, decl);2070 return sema.analyzeDeclRef(block, src, decl);
1440}2071}
14412072
1442fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2073fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1443 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;2074 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
1444 const src = inst_data.src();2075 const src = inst_data.src();
1445 const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key;2076 const decl_name = inst_data.get(sema.code);
2077 const decl = try sema.lookupIdentifier(block, src, decl_name);
1446 return sema.analyzeDeclVal(block, src, decl);2078 return sema.analyzeDeclVal(block, src, decl);
1447}2079}
14482080
1449fn zirCallNone(2081fn lookupIdentifier(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, name: []const u8) !*Decl {
1450 sema: *Sema,2082 // TODO emit a compile error if more than one decl would be matched.
1451 block: *Scope.Block,2083 var namespace = sema.namespace;
1452 inst: zir.Inst.Index,2084 while (true) {
1453 ensure_result_used: bool,2085 if (try sema.lookupInNamespace(namespace, name)) |decl| {
1454) InnerError!*Inst {2086 return decl;
1455 const tracy = trace(@src());2087 }
1456 defer tracy.end();2088 namespace = namespace.parent orelse break;
2089 }
2090 return sema.mod.fail(&block.base, src, "use of undeclared identifier '{s}'", .{name});
2091}
14572092
1458 const inst_data = sema.code.instructions.items(.data)[inst].un_node;2093/// This looks up a member of a specific namespace. It is affected by `usingnamespace` but
1459 const func_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };2094/// only for ones in the specified namespace.
2095fn lookupInNamespace(
2096 sema: *Sema,
2097 namespace: *Scope.Namespace,
2098 ident_name: []const u8,
2099) InnerError!?*Decl {
2100 const namespace_decl = namespace.getDecl();
2101 if (namespace_decl.analysis == .file_failure) {
2102 try sema.mod.declareDeclDependency(sema.owner_decl, namespace_decl);
2103 return error.AnalysisFail;
2104 }
14602105
1461 return sema.analyzeCall(block, inst_data.operand, func_src, inst_data.src(), .auto, ensure_result_used, &.{});2106 // TODO implement usingnamespace
2107 if (namespace.decls.get(ident_name)) |decl| {
2108 try sema.mod.declareDeclDependency(sema.owner_decl, decl);
2109 return decl;
2110 }
2111 log.debug("{*} ({s}) depends on non-existence of '{s}' in {*} ({s})", .{
2112 sema.owner_decl, sema.owner_decl.name, ident_name, namespace_decl, namespace_decl.name,
2113 });
2114 // TODO This dependency is too strong. Really, it should only be a dependency
2115 // on the non-existence of `ident_name` in the namespace. We can lessen the number of
2116 // outdated declarations by making this dependency more sophisticated.
2117 try sema.mod.declareDeclDependency(sema.owner_decl, namespace_decl);
2118 return null;
1462}2119}
14632120
1464fn zirCall(2121fn zirCall(
1465 sema: *Sema,2122 sema: *Sema,
1466 block: *Scope.Block,2123 block: *Scope.Block,
1467 inst: zir.Inst.Index,2124 inst: Zir.Inst.Index,
1468 modifier: std.builtin.CallOptions.Modifier,2125 modifier: std.builtin.CallOptions.Modifier,
1469 ensure_result_used: bool,2126 ensure_result_used: bool,
1470) InnerError!*Inst {2127) InnerError!*Inst {
...@@ -1474,7 +2131,7 @@ fn zirCall(...@@ -1474,7 +2131,7 @@ fn zirCall(
1474 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;2131 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1475 const func_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };2132 const func_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };
1476 const call_src = inst_data.src();2133 const call_src = inst_data.src();
1477 const extra = sema.code.extraData(zir.Inst.Call, inst_data.payload_index);2134 const extra = sema.code.extraData(Zir.Inst.Call, inst_data.payload_index);
1478 const args = sema.code.refSlice(extra.end, extra.data.args_len);2135 const args = sema.code.refSlice(extra.end, extra.data.args_len);
14792136
1480 return sema.analyzeCall(block, extra.data.callee, func_src, call_src, modifier, ensure_result_used, args);2137 return sema.analyzeCall(block, extra.data.callee, func_src, call_src, modifier, ensure_result_used, args);
...@@ -1483,12 +2140,12 @@ fn zirCall(...@@ -1483,12 +2140,12 @@ fn zirCall(
1483fn analyzeCall(2140fn analyzeCall(
1484 sema: *Sema,2141 sema: *Sema,
1485 block: *Scope.Block,2142 block: *Scope.Block,
1486 zir_func: zir.Inst.Ref,2143 zir_func: Zir.Inst.Ref,
1487 func_src: LazySrcLoc,2144 func_src: LazySrcLoc,
1488 call_src: LazySrcLoc,2145 call_src: LazySrcLoc,
1489 modifier: std.builtin.CallOptions.Modifier,2146 modifier: std.builtin.CallOptions.Modifier,
1490 ensure_result_used: bool,2147 ensure_result_used: bool,
1491 zir_args: []const zir.Inst.Ref,2148 zir_args: []const Zir.Inst.Ref,
1492) InnerError!*ir.Inst {2149) InnerError!*ir.Inst {
1493 const func = try sema.resolveInst(zir_func);2150 const func = try sema.resolveInst(zir_func);
14942151
...@@ -1527,11 +2184,20 @@ fn analyzeCall(...@@ -1527,11 +2184,20 @@ fn analyzeCall(
1527 );2184 );
1528 }2185 }
15292186
1530 if (modifier == .compile_time) {2187 switch (modifier) {
1531 return sema.mod.fail(&block.base, call_src, "TODO implement comptime function calls", .{});2188 .auto,
1532 }2189 .always_inline,
1533 if (modifier != .auto) {2190 .compile_time,
1534 return sema.mod.fail(&block.base, call_src, "TODO implement call with modifier {}", .{modifier});2191 => {},
2192
2193 .async_kw,
2194 .never_tail,
2195 .never_inline,
2196 .no_async,
2197 .always_tail,
2198 => return sema.mod.fail(&block.base, call_src, "TODO implement call with modifier {}", .{
2199 modifier,
2200 }),
1535 }2201 }
15362202
1537 // TODO handle function calls of generic functions2203 // TODO handle function calls of generic functions
...@@ -1579,24 +2245,38 @@ fn analyzeCall(...@@ -1579,24 +2245,38 @@ fn analyzeCall(
1579 .block_inst = block_inst,2245 .block_inst = block_inst,
1580 },2246 },
1581 };2247 };
1582 var inline_sema: Sema = .{2248 // In order to save a bit of stack space, directly modify Sema rather
1583 .mod = sema.mod,2249 // than create a child one.
1584 .gpa = sema.mod.gpa,2250 const parent_zir = sema.code;
1585 .arena = sema.arena,2251 sema.code = module_fn.owner_decl.namespace.file_scope.zir;
1586 .code = module_fn.zir,2252 defer sema.code = parent_zir;
1587 .inst_map = try sema.gpa.alloc(*ir.Inst, module_fn.zir.instructions.len),2253
1588 .owner_decl = sema.owner_decl,2254 const parent_inst_map = sema.inst_map;
1589 .owner_func = sema.owner_func,2255 sema.inst_map = .{};
1590 .func = module_fn,2256 defer {
1591 .param_inst_list = casted_args,2257 sema.inst_map.deinit(sema.gpa);
1592 .branch_quota = sema.branch_quota,2258 sema.inst_map = parent_inst_map;
1593 .branch_count = sema.branch_count,2259 }
1594 };2260
1595 defer sema.gpa.free(inline_sema.inst_map);2261 const parent_namespace = sema.namespace;
2262 sema.namespace = module_fn.owner_decl.namespace;
2263 defer sema.namespace = parent_namespace;
2264
2265 const parent_func = sema.func;
2266 sema.func = module_fn;
2267 defer sema.func = parent_func;
2268
2269 const parent_param_inst_list = sema.param_inst_list;
2270 sema.param_inst_list = casted_args;
2271 defer sema.param_inst_list = parent_param_inst_list;
2272
2273 const parent_next_arg_index = sema.next_arg_index;
2274 sema.next_arg_index = 0;
2275 defer sema.next_arg_index = parent_next_arg_index;
15962276
1597 var child_block: Scope.Block = .{2277 var child_block: Scope.Block = .{
1598 .parent = null,2278 .parent = null,
1599 .sema = &inline_sema,2279 .sema = sema,
1600 .src_decl = module_fn.owner_decl,2280 .src_decl = module_fn.owner_decl,
1601 .instructions = .{},2281 .instructions = .{},
1602 .label = null,2282 .label = null,
...@@ -1610,16 +2290,13 @@ fn analyzeCall(...@@ -1610,16 +2290,13 @@ fn analyzeCall(
1610 defer merges.results.deinit(sema.gpa);2290 defer merges.results.deinit(sema.gpa);
1611 defer merges.br_list.deinit(sema.gpa);2291 defer merges.br_list.deinit(sema.gpa);
16122292
1613 try inline_sema.emitBackwardBranch(&child_block, call_src);2293 try sema.emitBackwardBranch(&child_block, call_src);
16142294
1615 // This will have return instructions analyzed as break instructions to2295 // This will have return instructions analyzed as break instructions to
1616 // the block_inst above.2296 // the block_inst above.
1617 _ = try inline_sema.root(&child_block);2297 try sema.analyzeFnBody(&child_block, module_fn.zir_body_inst);
1618
1619 const result = try inline_sema.analyzeBlockBody(block, call_src, &child_block, merges);
16202298
1621 sema.branch_quota = inline_sema.branch_quota;2299 const result = try sema.analyzeBlockBody(block, call_src, &child_block, merges);
1622 sema.branch_count = inline_sema.branch_count;
16232300
1624 break :res result;2301 break :res result;
1625 } else res: {2302 } else res: {
...@@ -1633,7 +2310,7 @@ fn analyzeCall(...@@ -1633,7 +2310,7 @@ fn analyzeCall(
1633 return result;2310 return result;
1634}2311}
16352312
1636fn zirIntType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2313fn zirIntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1637 const tracy = trace(@src());2314 const tracy = trace(@src());
1638 defer tracy.end();2315 defer tracy.end();
16392316
...@@ -1644,7 +2321,7 @@ fn zirIntType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -1644,7 +2321,7 @@ fn zirIntType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
1644 return sema.mod.constType(sema.arena, src, ty);2321 return sema.mod.constType(sema.arena, src, ty);
1645}2322}
16462323
1647fn zirOptionalType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2324fn zirOptionalType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1648 const tracy = trace(@src());2325 const tracy = trace(@src());
1649 defer tracy.end();2326 defer tracy.end();
16502327
...@@ -1656,19 +2333,30 @@ fn zirOptionalType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inner...@@ -1656,19 +2333,30 @@ fn zirOptionalType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inner
1656 return sema.mod.constType(sema.arena, src, opt_type);2333 return sema.mod.constType(sema.arena, src, opt_type);
1657}2334}
16582335
1659fn zirOptionalTypeFromPtrElem(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2336fn zirElemType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1660 const tracy = trace(@src());
1661 defer tracy.end();
1662
1663 const inst_data = sema.code.instructions.items(.data)[inst].un_node;2337 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1664 const ptr = try sema.resolveInst(inst_data.operand);2338 const src = inst_data.src();
1665 const elem_ty = ptr.ty.elemType();2339 const array_type = try sema.resolveType(block, src, inst_data.operand);
1666 const opt_ty = try sema.mod.optionalType(sema.arena, elem_ty);2340 const elem_type = array_type.elemType();
2341 return sema.mod.constType(sema.arena, src, elem_type);
2342}
16672343
1668 return sema.mod.constType(sema.arena, inst_data.src(), opt_ty);2344fn zirVectorType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2345 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2346 const src = inst_data.src();
2347 const elem_type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
2348 const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
2349 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2350 const len = try sema.resolveAlreadyCoercedInt(block, len_src, extra.lhs, u32);
2351 const elem_type = try sema.resolveType(block, elem_type_src, extra.rhs);
2352 const vector_type = try Type.Tag.vector.create(sema.arena, .{
2353 .len = len,
2354 .elem_type = elem_type,
2355 });
2356 return sema.mod.constType(sema.arena, src, vector_type);
1669}2357}
16702358
1671fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2359fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1672 const tracy = trace(@src());2360 const tracy = trace(@src());
1673 defer tracy.end();2361 defer tracy.end();
16742362
...@@ -1681,14 +2369,14 @@ fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr...@@ -1681,14 +2369,14 @@ fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
1681 return sema.mod.constType(sema.arena, .unneeded, array_ty);2369 return sema.mod.constType(sema.arena, .unneeded, array_ty);
1682}2370}
16832371
1684fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2372fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1685 const tracy = trace(@src());2373 const tracy = trace(@src());
1686 defer tracy.end();2374 defer tracy.end();
16872375
1688 // TODO these should be lazily evaluated2376 // TODO these should be lazily evaluated
1689 const inst_data = sema.code.instructions.items(.data)[inst].array_type_sentinel;2377 const inst_data = sema.code.instructions.items(.data)[inst].array_type_sentinel;
1690 const len = try sema.resolveInstConst(block, .unneeded, inst_data.len);2378 const len = try sema.resolveInstConst(block, .unneeded, inst_data.len);
1691 const extra = sema.code.extraData(zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;2379 const extra = sema.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;
1692 const sentinel = try sema.resolveInstConst(block, .unneeded, extra.sentinel);2380 const sentinel = try sema.resolveInstConst(block, .unneeded, extra.sentinel);
1693 const elem_type = try sema.resolveType(block, .unneeded, extra.elem_type);2381 const elem_type = try sema.resolveType(block, .unneeded, extra.elem_type);
1694 const array_ty = try sema.mod.arrayType(sema.arena, len.val.toUnsignedInt(), sentinel.val, elem_type);2382 const array_ty = try sema.mod.arrayType(sema.arena, len.val.toUnsignedInt(), sentinel.val, elem_type);
...@@ -1696,12 +2384,25 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index)...@@ -1696,12 +2384,25 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index)
1696 return sema.mod.constType(sema.arena, .unneeded, array_ty);2384 return sema.mod.constType(sema.arena, .unneeded, array_ty);
1697}2385}
16982386
1699fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2387fn zirAnyframeType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2388 const tracy = trace(@src());
2389 defer tracy.end();
2390
2391 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
2392 const src = inst_data.src();
2393 const operand_src: LazySrcLoc = .{ .node_offset_anyframe_type = inst_data.src_node };
2394 const return_type = try sema.resolveType(block, operand_src, inst_data.operand);
2395 const anyframe_type = try Type.Tag.anyframe_T.create(sema.arena, return_type);
2396
2397 return sema.mod.constType(sema.arena, src, anyframe_type);
2398}
2399
2400fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1700 const tracy = trace(@src());2401 const tracy = trace(@src());
1701 defer tracy.end();2402 defer tracy.end();
17022403
1703 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;2404 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1704 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;2405 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1705 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };2406 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
1706 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };2407 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
1707 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };2408 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
...@@ -1717,7 +2418,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn...@@ -1717,7 +2418,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn
1717 return sema.mod.constType(sema.arena, src, err_union_ty);2418 return sema.mod.constType(sema.arena, src, err_union_ty);
1718}2419}
17192420
1720fn zirErrorValue(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2421fn zirErrorValue(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1721 const tracy = trace(@src());2422 const tracy = trace(@src());
1722 defer tracy.end();2423 defer tracy.end();
17232424
...@@ -1735,7 +2436,7 @@ fn zirErrorValue(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr...@@ -1735,7 +2436,7 @@ fn zirErrorValue(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
1735 });2436 });
1736}2437}
17372438
1738fn zirErrorToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2439fn zirErrorToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1739 const tracy = trace(@src());2440 const tracy = trace(@src());
1740 defer tracy.end();2441 defer tracy.end();
17412442
...@@ -1744,24 +2445,28 @@ fn zirErrorToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr...@@ -1744,24 +2445,28 @@ fn zirErrorToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
1744 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };2445 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1745 const op = try sema.resolveInst(inst_data.operand);2446 const op = try sema.resolveInst(inst_data.operand);
1746 const op_coerced = try sema.coerce(block, Type.initTag(.anyerror), op, operand_src);2447 const op_coerced = try sema.coerce(block, Type.initTag(.anyerror), op, operand_src);
2448 const result_ty = Type.initTag(.u16);
17472449
1748 if (op_coerced.value()) |val| {2450 if (try sema.resolvePossiblyUndefinedValue(block, src, op_coerced)) |val| {
2451 if (val.isUndef()) {
2452 return sema.mod.constUndef(sema.arena, src, result_ty);
2453 }
1749 const payload = try sema.arena.create(Value.Payload.U64);2454 const payload = try sema.arena.create(Value.Payload.U64);
1750 payload.* = .{2455 payload.* = .{
1751 .base = .{ .tag = .int_u64 },2456 .base = .{ .tag = .int_u64 },
1752 .data = (try sema.mod.getErrorValue(val.castTag(.@"error").?.data.name)).value,2457 .data = (try sema.mod.getErrorValue(val.castTag(.@"error").?.data.name)).value,
1753 };2458 };
1754 return sema.mod.constInst(sema.arena, src, .{2459 return sema.mod.constInst(sema.arena, src, .{
1755 .ty = Type.initTag(.u16),2460 .ty = result_ty,
1756 .val = Value.initPayload(&payload.base),2461 .val = Value.initPayload(&payload.base),
1757 });2462 });
1758 }2463 }
17592464
1760 try sema.requireRuntimeBlock(block, src);2465 try sema.requireRuntimeBlock(block, src);
1761 return block.addUnOp(src, Type.initTag(.u16), .error_to_int, op_coerced);2466 return block.addUnOp(src, result_ty, .error_to_int, op_coerced);
1762}2467}
17632468
1764fn zirIntToError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2469fn zirIntToError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1765 const tracy = trace(@src());2470 const tracy = trace(@src());
1766 defer tracy.end();2471 defer tracy.end();
17672472
...@@ -1794,12 +2499,12 @@ fn zirIntToError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr...@@ -1794,12 +2499,12 @@ fn zirIntToError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
1794 return block.addUnOp(src, Type.initTag(.anyerror), .int_to_error, op);2499 return block.addUnOp(src, Type.initTag(.anyerror), .int_to_error, op);
1795}2500}
17962501
1797fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2502fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1798 const tracy = trace(@src());2503 const tracy = trace(@src());
1799 defer tracy.end();2504 defer tracy.end();
18002505
1801 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;2506 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1802 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;2507 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1803 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };2508 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
1804 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };2509 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
1805 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };2510 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
...@@ -1873,7 +2578,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn...@@ -1873,7 +2578,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn
1873 });2578 });
1874}2579}
18752580
1876fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2581fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1877 const tracy = trace(@src());2582 const tracy = trace(@src());
1878 defer tracy.end();2583 defer tracy.end();
18792584
...@@ -1886,20 +2591,7 @@ fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE...@@ -1886,20 +2591,7 @@ fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE
1886 });2591 });
1887}2592}
18882593
1889fn zirEnumLiteralSmall(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2594fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1890 const tracy = trace(@src());
1891 defer tracy.end();
1892
1893 const name = sema.code.instructions.items(.data)[inst].small_str.get();
1894 const src: LazySrcLoc = .unneeded;
1895 const duped_name = try sema.arena.dupe(u8, name);
1896 return sema.mod.constInst(sema.arena, src, .{
1897 .ty = Type.initTag(.enum_literal),
1898 .val = try Value.Tag.enum_literal.create(sema.arena, duped_name),
1899 });
1900}
1901
1902fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1903 const mod = sema.mod;2595 const mod = sema.mod;
1904 const arena = sema.arena;2596 const arena = sema.arena;
1905 const inst_data = sema.code.instructions.items(.data)[inst].un_node;2597 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
...@@ -1930,7 +2622,7 @@ fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr...@@ -1930,7 +2622,7 @@ fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
1930 var int_tag_type_buffer: Type.Payload.Bits = undefined;2622 var int_tag_type_buffer: Type.Payload.Bits = undefined;
1931 const int_tag_ty = try enum_tag.ty.intTagType(&int_tag_type_buffer).copy(arena);2623 const int_tag_ty = try enum_tag.ty.intTagType(&int_tag_type_buffer).copy(arena);
19322624
1933 if (enum_tag.ty.onePossibleValue()) |opv| {2625 if (try sema.typeHasOnePossibleValue(block, src, enum_tag.ty)) |opv| {
1934 return mod.constInst(arena, src, .{2626 return mod.constInst(arena, src, .{
1935 .ty = int_tag_ty,2627 .ty = int_tag_ty,
1936 .val = opv,2628 .val = opv,
...@@ -1981,12 +2673,12 @@ fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr...@@ -1981,12 +2673,12 @@ fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
1981 return block.addUnOp(src, int_tag_ty, .bitcast, enum_tag);2673 return block.addUnOp(src, int_tag_ty, .bitcast, enum_tag);
1982}2674}
19832675
1984fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2676fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1985 const mod = sema.mod;2677 const mod = sema.mod;
1986 const target = mod.getTarget();2678 const target = mod.getTarget();
1987 const arena = sema.arena;2679 const arena = sema.arena;
1988 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;2680 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1989 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;2681 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1990 const src = inst_data.src();2682 const src = inst_data.src();
1991 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };2683 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1992 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };2684 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
...@@ -2040,7 +2732,7 @@ fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr...@@ -2040,7 +2732,7 @@ fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
2040fn zirOptionalPayloadPtr(2732fn zirOptionalPayloadPtr(
2041 sema: *Sema,2733 sema: *Sema,
2042 block: *Scope.Block,2734 block: *Scope.Block,
2043 inst: zir.Inst.Index,2735 inst: Zir.Inst.Index,
2044 safety_check: bool,2736 safety_check: bool,
2045) InnerError!*Inst {2737) InnerError!*Inst {
2046 const tracy = trace(@src());2738 const tracy = trace(@src());
...@@ -2083,7 +2775,7 @@ fn zirOptionalPayloadPtr(...@@ -2083,7 +2775,7 @@ fn zirOptionalPayloadPtr(
2083fn zirOptionalPayload(2775fn zirOptionalPayload(
2084 sema: *Sema,2776 sema: *Sema,
2085 block: *Scope.Block,2777 block: *Scope.Block,
2086 inst: zir.Inst.Index,2778 inst: Zir.Inst.Index,
2087 safety_check: bool,2779 safety_check: bool,
2088) InnerError!*Inst {2780) InnerError!*Inst {
2089 const tracy = trace(@src());2781 const tracy = trace(@src());
...@@ -2121,7 +2813,7 @@ fn zirOptionalPayload(...@@ -2121,7 +2813,7 @@ fn zirOptionalPayload(
2121fn zirErrUnionPayload(2813fn zirErrUnionPayload(
2122 sema: *Sema,2814 sema: *Sema,
2123 block: *Scope.Block,2815 block: *Scope.Block,
2124 inst: zir.Inst.Index,2816 inst: Zir.Inst.Index,
2125 safety_check: bool,2817 safety_check: bool,
2126) InnerError!*Inst {2818) InnerError!*Inst {
2127 const tracy = trace(@src());2819 const tracy = trace(@src());
...@@ -2155,7 +2847,7 @@ fn zirErrUnionPayload(...@@ -2155,7 +2847,7 @@ fn zirErrUnionPayload(
2155fn zirErrUnionPayloadPtr(2847fn zirErrUnionPayloadPtr(
2156 sema: *Sema,2848 sema: *Sema,
2157 block: *Scope.Block,2849 block: *Scope.Block,
2158 inst: zir.Inst.Index,2850 inst: Zir.Inst.Index,
2159 safety_check: bool,2851 safety_check: bool,
2160) InnerError!*Inst {2852) InnerError!*Inst {
2161 const tracy = trace(@src());2853 const tracy = trace(@src());
...@@ -2196,7 +2888,7 @@ fn zirErrUnionPayloadPtr(...@@ -2196,7 +2888,7 @@ fn zirErrUnionPayloadPtr(
2196}2888}
21972889
2198/// Value in, value out2890/// Value in, value out
2199fn zirErrUnionCode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2891fn zirErrUnionCode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2200 const tracy = trace(@src());2892 const tracy = trace(@src());
2201 defer tracy.end();2893 defer tracy.end();
22022894
...@@ -2220,7 +2912,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inner...@@ -2220,7 +2912,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inner
2220}2912}
22212913
2222/// Pointer in, value out2914/// Pointer in, value out
2223fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2915fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2224 const tracy = trace(@src());2916 const tracy = trace(@src());
2225 defer tracy.end();2917 defer tracy.end();
22262918
...@@ -2246,7 +2938,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In...@@ -2246,7 +2938,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In
2246 return block.addUnOp(src, operand.ty.castTag(.error_union).?.data.payload, .unwrap_errunion_err_ptr, operand);2938 return block.addUnOp(src, operand.ty.castTag(.error_union).?.data.payload, .unwrap_errunion_err_ptr, operand);
2247}2939}
22482940
2249fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {2941fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
2250 const tracy = trace(@src());2942 const tracy = trace(@src());
2251 defer tracy.end();2943 defer tracy.end();
22522944
...@@ -2260,102 +2952,190 @@ fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Inde...@@ -2260,102 +2952,190 @@ fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Inde
2260 }2952 }
2261}2953}
22622954
2263fn zirFnType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args: bool) InnerError!*Inst {2955fn zirFunc(
2956 sema: *Sema,
2957 block: *Scope.Block,
2958 inst: Zir.Inst.Index,
2959 inferred_error_set: bool,
2960) InnerError!*Inst {
2264 const tracy = trace(@src());2961 const tracy = trace(@src());
2265 defer tracy.end();2962 defer tracy.end();
22662963
2267 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;2964 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2268 const src = inst_data.src();2965 const src = inst_data.src();
2269 const extra = sema.code.extraData(zir.Inst.FnType, inst_data.payload_index);2966 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
2270 const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);2967 const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
22712968
2272 return sema.fnTypeCommon(2969 var body_inst: Zir.Inst.Index = 0;
2273 block,2970 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
2274 inst_data.src_node,2971 if (extra.data.body_len != 0) {
2275 param_types,2972 body_inst = inst;
2276 extra.data.return_type,2973 const extra_index = extra.end + extra.data.param_types_len + extra.data.body_len;
2277 .Unspecified,2974 src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
2278 var_args,2975 }
2279 );
2280}
2281
2282fn zirFnTypeCc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args: bool) InnerError!*Inst {
2283 const tracy = trace(@src());
2284 defer tracy.end();
22852976
2286 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;2977 const cc: std.builtin.CallingConvention = if (sema.owner_decl.is_exported)
2287 const src = inst_data.src();2978 .C
2288 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = inst_data.src_node };2979 else
2289 const extra = sema.code.extraData(zir.Inst.FnTypeCc, inst_data.payload_index);2980 .Unspecified;
2290 const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
22912981
2292 const cc_tv = try sema.resolveInstConst(block, cc_src, extra.data.cc);2982 return sema.funcCommon(
2293 // TODO once we're capable of importing and analyzing decls from
2294 // std.builtin, this needs to change
2295 const cc_str = cc_tv.val.castTag(.enum_literal).?.data;
2296 const cc = std.meta.stringToEnum(std.builtin.CallingConvention, cc_str) orelse
2297 return sema.mod.fail(&block.base, cc_src, "Unknown calling convention {s}", .{cc_str});
2298 return sema.fnTypeCommon(
2299 block,2983 block,
2300 inst_data.src_node,2984 inst_data.src_node,
2301 param_types,2985 param_types,
2986 body_inst,
2302 extra.data.return_type,2987 extra.data.return_type,
2303 cc,2988 cc,
2304 var_args,2989 Value.initTag(.null_value),
2990 false,
2991 inferred_error_set,
2992 false,
2993 src_locs,
2994 null,
2305 );2995 );
2306}2996}
23072997
2308fn fnTypeCommon(2998fn funcCommon(
2309 sema: *Sema,2999 sema: *Sema,
2310 block: *Scope.Block,3000 block: *Scope.Block,
2311 src_node_offset: i32,3001 src_node_offset: i32,
2312 zir_param_types: []const zir.Inst.Ref,3002 zir_param_types: []const Zir.Inst.Ref,
2313 zir_return_type: zir.Inst.Ref,3003 body_inst: Zir.Inst.Index,
3004 zir_return_type: Zir.Inst.Ref,
2314 cc: std.builtin.CallingConvention,3005 cc: std.builtin.CallingConvention,
3006 align_val: Value,
2315 var_args: bool,3007 var_args: bool,
3008 inferred_error_set: bool,
3009 is_extern: bool,
3010 src_locs: Zir.Inst.Func.SrcLocs,
3011 opt_lib_name: ?[]const u8,
2316) InnerError!*Inst {3012) InnerError!*Inst {
2317 const src: LazySrcLoc = .{ .node_offset = src_node_offset };3013 const src: LazySrcLoc = .{ .node_offset = src_node_offset };
2318 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };3014 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
2319 const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type);3015 const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type);
23203016
2321 // Hot path for some common function types.3017 const mod = sema.mod;
2322 if (zir_param_types.len == 0 and !var_args) {3018
2323 if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {3019 const fn_ty: Type = fn_ty: {
2324 return sema.mod.constType(sema.arena, src, Type.initTag(.fn_noreturn_no_args));3020 // Hot path for some common function types.
3021 if (zir_param_types.len == 0 and !var_args and align_val.tag() == .null_value) {
3022 if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
3023 break :fn_ty Type.initTag(.fn_noreturn_no_args);
3024 }
3025
3026 if (return_type.zigTypeTag() == .Void and cc == .Unspecified) {
3027 break :fn_ty Type.initTag(.fn_void_no_args);
3028 }
3029
3030 if (return_type.zigTypeTag() == .NoReturn and cc == .Naked) {
3031 break :fn_ty Type.initTag(.fn_naked_noreturn_no_args);
3032 }
3033
3034 if (return_type.zigTypeTag() == .Void and cc == .C) {
3035 break :fn_ty Type.initTag(.fn_ccc_void_no_args);
3036 }
2325 }3037 }
23263038
2327 if (return_type.zigTypeTag() == .Void and cc == .Unspecified) {3039 const param_types = try sema.arena.alloc(Type, zir_param_types.len);
2328 return sema.mod.constType(sema.arena, src, Type.initTag(.fn_void_no_args));3040 for (zir_param_types) |param_type, i| {
3041 // TODO make a compile error from `resolveType` report the source location
3042 // of the specific parameter. Will need to take a similar strategy as
3043 // `resolveSwitchItemVal` to avoid resolving the source location unless
3044 // we actually need to report an error.
3045 param_types[i] = try sema.resolveType(block, src, param_type);
2329 }3046 }
23303047
2331 if (return_type.zigTypeTag() == .NoReturn and cc == .Naked) {3048 if (align_val.tag() != .null_value) {
2332 return sema.mod.constType(sema.arena, src, Type.initTag(.fn_naked_noreturn_no_args));3049 return mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{});
2333 }3050 }
23343051
2335 if (return_type.zigTypeTag() == .Void and cc == .C) {3052 break :fn_ty try Type.Tag.function.create(sema.arena, .{
2336 return sema.mod.constType(sema.arena, src, Type.initTag(.fn_ccc_void_no_args));3053 .param_types = param_types,
3054 .return_type = return_type,
3055 .cc = cc,
3056 .is_var_args = var_args,
3057 });
3058 };
3059
3060 if (opt_lib_name) |lib_name| blk: {
3061 const lib_name_src: LazySrcLoc = .{ .node_offset_lib_name = src_node_offset };
3062 log.debug("extern fn symbol expected in lib '{s}'", .{lib_name});
3063 mod.comp.stage1AddLinkLib(lib_name) catch |err| {
3064 return mod.fail(&block.base, lib_name_src, "unable to add link lib '{s}': {s}", .{
3065 lib_name, @errorName(err),
3066 });
3067 };
3068 const target = mod.getTarget();
3069 if (target_util.is_libc_lib_name(target, lib_name)) {
3070 if (!mod.comp.bin_file.options.link_libc) {
3071 return mod.fail(
3072 &block.base,
3073 lib_name_src,
3074 "dependency on libc must be explicitly specified in the build command",
3075 .{},
3076 );
3077 }
3078 break :blk;
3079 }
3080 if (target_util.is_libcpp_lib_name(target, lib_name)) {
3081 if (!mod.comp.bin_file.options.link_libcpp) {
3082 return mod.fail(
3083 &block.base,
3084 lib_name_src,
3085 "dependency on libc++ must be explicitly specified in the build command",
3086 .{},
3087 );
3088 }
3089 break :blk;
3090 }
3091 if (!target.isWasm() and !mod.comp.bin_file.options.pic) {
3092 return mod.fail(
3093 &block.base,
3094 lib_name_src,
3095 "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
3096 .{ lib_name, lib_name },
3097 );
2337 }3098 }
2338 }3099 }
23393100
2340 const param_types = try sema.arena.alloc(Type, zir_param_types.len);3101 if (is_extern) {
2341 for (zir_param_types) |param_type, i| {3102 return sema.mod.constInst(sema.arena, src, .{
2342 // TODO make a compile error from `resolveType` report the source location3103 .ty = fn_ty,
2343 // of the specific parameter. Will need to take a similar strategy as3104 .val = try Value.Tag.extern_fn.create(sema.arena, sema.owner_decl),
2344 // `resolveSwitchItemVal` to avoid resolving the source location unless3105 });
2345 // we actually need to report an error.3106 }
2346 param_types[i] = try sema.resolveType(block, src, param_type);3107
3108 if (body_inst == 0) {
3109 return mod.constType(sema.arena, src, fn_ty);
2347 }3110 }
23483111
2349 const fn_ty = try Type.Tag.function.create(sema.arena, .{3112 const is_inline = fn_ty.fnCallingConvention() == .Inline;
2350 .param_types = param_types,3113 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .queued;
2351 .return_type = return_type,3114
2352 .cc = cc,3115 const fn_payload = try sema.arena.create(Value.Payload.Function);
2353 .is_var_args = var_args,3116 const new_func = try sema.gpa.create(Module.Fn);
3117 new_func.* = .{
3118 .state = anal_state,
3119 .zir_body_inst = body_inst,
3120 .owner_decl = sema.owner_decl,
3121 .body = undefined,
3122 .lbrace_line = src_locs.lbrace_line,
3123 .rbrace_line = src_locs.rbrace_line,
3124 .lbrace_column = @truncate(u16, src_locs.columns),
3125 .rbrace_column = @truncate(u16, src_locs.columns >> 16),
3126 };
3127 fn_payload.* = .{
3128 .base = .{ .tag = .function },
3129 .data = new_func,
3130 };
3131 const result = try sema.mod.constInst(sema.arena, src, .{
3132 .ty = fn_ty,
3133 .val = Value.initPayload(&fn_payload.base),
2354 });3134 });
2355 return sema.mod.constType(sema.arena, src, fn_ty);3135 return result;
2356}3136}
23573137
2358fn zirAs(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3138fn zirAs(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2359 const tracy = trace(@src());3139 const tracy = trace(@src());
2360 defer tracy.end();3140 defer tracy.end();
23613141
...@@ -2363,13 +3143,13 @@ fn zirAs(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Ins...@@ -2363,13 +3143,13 @@ fn zirAs(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Ins
2363 return sema.analyzeAs(block, .unneeded, bin_inst.lhs, bin_inst.rhs);3143 return sema.analyzeAs(block, .unneeded, bin_inst.lhs, bin_inst.rhs);
2364}3144}
23653145
2366fn zirAsNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3146fn zirAsNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2367 const tracy = trace(@src());3147 const tracy = trace(@src());
2368 defer tracy.end();3148 defer tracy.end();
23693149
2370 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3150 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2371 const src = inst_data.src();3151 const src = inst_data.src();
2372 const extra = sema.code.extraData(zir.Inst.As, inst_data.payload_index).data;3152 const extra = sema.code.extraData(Zir.Inst.As, inst_data.payload_index).data;
2373 return sema.analyzeAs(block, src, extra.dest_type, extra.operand);3153 return sema.analyzeAs(block, src, extra.dest_type, extra.operand);
2374}3154}
23753155
...@@ -2377,15 +3157,15 @@ fn analyzeAs(...@@ -2377,15 +3157,15 @@ fn analyzeAs(
2377 sema: *Sema,3157 sema: *Sema,
2378 block: *Scope.Block,3158 block: *Scope.Block,
2379 src: LazySrcLoc,3159 src: LazySrcLoc,
2380 zir_dest_type: zir.Inst.Ref,3160 zir_dest_type: Zir.Inst.Ref,
2381 zir_operand: zir.Inst.Ref,3161 zir_operand: Zir.Inst.Ref,
2382) InnerError!*Inst {3162) InnerError!*Inst {
2383 const dest_type = try sema.resolveType(block, src, zir_dest_type);3163 const dest_type = try sema.resolveType(block, src, zir_dest_type);
2384 const operand = try sema.resolveInst(zir_operand);3164 const operand = try sema.resolveInst(zir_operand);
2385 return sema.coerce(block, dest_type, operand, src);3165 return sema.coerce(block, dest_type, operand, src);
2386}3166}
23873167
2388fn zirPtrtoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3168fn zirPtrToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2389 const tracy = trace(@src());3169 const tracy = trace(@src());
2390 defer tracy.end();3170 defer tracy.end();
23913171
...@@ -2402,14 +3182,14 @@ fn zirPtrtoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro...@@ -2402,14 +3182,14 @@ fn zirPtrtoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
2402 return block.addUnOp(src, ty, .ptrtoint, ptr);3182 return block.addUnOp(src, ty, .ptrtoint, ptr);
2403}3183}
24043184
2405fn zirFieldVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3185fn zirFieldVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2406 const tracy = trace(@src());3186 const tracy = trace(@src());
2407 defer tracy.end();3187 defer tracy.end();
24083188
2409 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3189 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2410 const src = inst_data.src();3190 const src = inst_data.src();
2411 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };3191 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
2412 const extra = sema.code.extraData(zir.Inst.Field, inst_data.payload_index).data;3192 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
2413 const field_name = sema.code.nullTerminatedString(extra.field_name_start);3193 const field_name = sema.code.nullTerminatedString(extra.field_name_start);
2414 const object = try sema.resolveInst(extra.lhs);3194 const object = try sema.resolveInst(extra.lhs);
2415 const object_ptr = if (object.ty.zigTypeTag() == .Pointer)3195 const object_ptr = if (object.ty.zigTypeTag() == .Pointer)
...@@ -2420,27 +3200,27 @@ fn zirFieldVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro...@@ -2420,27 +3200,27 @@ fn zirFieldVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
2420 return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);3200 return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);
2421}3201}
24223202
2423fn zirFieldPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3203fn zirFieldPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2424 const tracy = trace(@src());3204 const tracy = trace(@src());
2425 defer tracy.end();3205 defer tracy.end();
24263206
2427 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3207 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2428 const src = inst_data.src();3208 const src = inst_data.src();
2429 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };3209 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
2430 const extra = sema.code.extraData(zir.Inst.Field, inst_data.payload_index).data;3210 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
2431 const field_name = sema.code.nullTerminatedString(extra.field_name_start);3211 const field_name = sema.code.nullTerminatedString(extra.field_name_start);
2432 const object_ptr = try sema.resolveInst(extra.lhs);3212 const object_ptr = try sema.resolveInst(extra.lhs);
2433 return sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);3213 return sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);
2434}3214}
24353215
2436fn zirFieldValNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3216fn zirFieldValNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2437 const tracy = trace(@src());3217 const tracy = trace(@src());
2438 defer tracy.end();3218 defer tracy.end();
24393219
2440 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3220 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2441 const src = inst_data.src();3221 const src = inst_data.src();
2442 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };3222 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
2443 const extra = sema.code.extraData(zir.Inst.FieldNamed, inst_data.payload_index).data;3223 const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
2444 const object = try sema.resolveInst(extra.lhs);3224 const object = try sema.resolveInst(extra.lhs);
2445 const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name);3225 const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name);
2446 const object_ptr = try sema.analyzeRef(block, src, object);3226 const object_ptr = try sema.analyzeRef(block, src, object);
...@@ -2448,20 +3228,20 @@ fn zirFieldValNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inne...@@ -2448,20 +3228,20 @@ fn zirFieldValNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inne
2448 return sema.analyzeLoad(block, src, result_ptr, src);3228 return sema.analyzeLoad(block, src, result_ptr, src);
2449}3229}
24503230
2451fn zirFieldPtrNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3231fn zirFieldPtrNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2452 const tracy = trace(@src());3232 const tracy = trace(@src());
2453 defer tracy.end();3233 defer tracy.end();
24543234
2455 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3235 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2456 const src = inst_data.src();3236 const src = inst_data.src();
2457 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };3237 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
2458 const extra = sema.code.extraData(zir.Inst.FieldNamed, inst_data.payload_index).data;3238 const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
2459 const object_ptr = try sema.resolveInst(extra.lhs);3239 const object_ptr = try sema.resolveInst(extra.lhs);
2460 const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name);3240 const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name);
2461 return sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);3241 return sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);
2462}3242}
24633243
2464fn zirIntcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3244fn zirIntCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2465 const tracy = trace(@src());3245 const tracy = trace(@src());
2466 defer tracy.end();3246 defer tracy.end();
24673247
...@@ -2469,7 +3249,7 @@ fn zirIntcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -2469,7 +3249,7 @@ fn zirIntcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
2469 const src = inst_data.src();3249 const src = inst_data.src();
2470 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };3250 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
2471 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };3251 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
2472 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;3252 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
24733253
2474 const dest_type = try sema.resolveType(block, dest_ty_src, extra.lhs);3254 const dest_type = try sema.resolveType(block, dest_ty_src, extra.lhs);
2475 const operand = try sema.resolveInst(extra.rhs);3255 const operand = try sema.resolveInst(extra.rhs);
...@@ -2504,7 +3284,7 @@ fn zirIntcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -2504,7 +3284,7 @@ fn zirIntcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
2504 return sema.mod.fail(&block.base, src, "TODO implement analyze widen or shorten int", .{});3284 return sema.mod.fail(&block.base, src, "TODO implement analyze widen or shorten int", .{});
2505}3285}
25063286
2507fn zirBitcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3287fn zirBitcast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2508 const tracy = trace(@src());3288 const tracy = trace(@src());
2509 defer tracy.end();3289 defer tracy.end();
25103290
...@@ -2512,14 +3292,14 @@ fn zirBitcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -2512,14 +3292,14 @@ fn zirBitcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
2512 const src = inst_data.src();3292 const src = inst_data.src();
2513 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };3293 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
2514 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };3294 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
2515 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;3295 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
25163296
2517 const dest_type = try sema.resolveType(block, dest_ty_src, extra.lhs);3297 const dest_type = try sema.resolveType(block, dest_ty_src, extra.lhs);
2518 const operand = try sema.resolveInst(extra.rhs);3298 const operand = try sema.resolveInst(extra.rhs);
2519 return sema.bitcast(block, dest_type, operand);3299 return sema.bitcast(block, dest_type, operand);
2520}3300}
25213301
2522fn zirFloatcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3302fn zirFloatCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2523 const tracy = trace(@src());3303 const tracy = trace(@src());
2524 defer tracy.end();3304 defer tracy.end();
25253305
...@@ -2527,7 +3307,7 @@ fn zirFloatcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr...@@ -2527,7 +3307,7 @@ fn zirFloatcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
2527 const src = inst_data.src();3307 const src = inst_data.src();
2528 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };3308 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
2529 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };3309 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
2530 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;3310 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
25313311
2532 const dest_type = try sema.resolveType(block, dest_ty_src, extra.lhs);3312 const dest_type = try sema.resolveType(block, dest_ty_src, extra.lhs);
2533 const operand = try sema.resolveInst(extra.rhs);3313 const operand = try sema.resolveInst(extra.rhs);
...@@ -2562,7 +3342,7 @@ fn zirFloatcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr...@@ -2562,7 +3342,7 @@ fn zirFloatcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
2562 return sema.mod.fail(&block.base, src, "TODO implement analyze widen or shorten float", .{});3342 return sema.mod.fail(&block.base, src, "TODO implement analyze widen or shorten float", .{});
2563}3343}
25643344
2565fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3345fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2566 const tracy = trace(@src());3346 const tracy = trace(@src());
2567 defer tracy.end();3347 defer tracy.end();
25683348
...@@ -2577,14 +3357,14 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -2577,14 +3357,14 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
2577 return sema.analyzeLoad(block, sema.src, result_ptr, sema.src);3357 return sema.analyzeLoad(block, sema.src, result_ptr, sema.src);
2578}3358}
25793359
2580fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3360fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2581 const tracy = trace(@src());3361 const tracy = trace(@src());
2582 defer tracy.end();3362 defer tracy.end();
25833363
2584 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3364 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2585 const src = inst_data.src();3365 const src = inst_data.src();
2586 const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node };3366 const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node };
2587 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;3367 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2588 const array = try sema.resolveInst(extra.lhs);3368 const array = try sema.resolveInst(extra.lhs);
2589 const array_ptr = if (array.ty.zigTypeTag() == .Pointer)3369 const array_ptr = if (array.ty.zigTypeTag() == .Pointer)
2590 array3370 array
...@@ -2595,7 +3375,7 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE...@@ -2595,7 +3375,7 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE
2595 return sema.analyzeLoad(block, src, result_ptr, src);3375 return sema.analyzeLoad(block, src, result_ptr, src);
2596}3376}
25973377
2598fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3378fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2599 const tracy = trace(@src());3379 const tracy = trace(@src());
2600 defer tracy.end();3380 defer tracy.end();
26013381
...@@ -2605,39 +3385,39 @@ fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -2605,39 +3385,39 @@ fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
2605 return sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src);3385 return sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src);
2606}3386}
26073387
2608fn zirElemPtrNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3388fn zirElemPtrNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2609 const tracy = trace(@src());3389 const tracy = trace(@src());
2610 defer tracy.end();3390 defer tracy.end();
26113391
2612 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3392 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2613 const src = inst_data.src();3393 const src = inst_data.src();
2614 const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node };3394 const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node };
2615 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;3395 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2616 const array_ptr = try sema.resolveInst(extra.lhs);3396 const array_ptr = try sema.resolveInst(extra.lhs);
2617 const elem_index = try sema.resolveInst(extra.rhs);3397 const elem_index = try sema.resolveInst(extra.rhs);
2618 return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src);3398 return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src);
2619}3399}
26203400
2621fn zirSliceStart(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3401fn zirSliceStart(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2622 const tracy = trace(@src());3402 const tracy = trace(@src());
2623 defer tracy.end();3403 defer tracy.end();
26243404
2625 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3405 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2626 const src = inst_data.src();3406 const src = inst_data.src();
2627 const extra = sema.code.extraData(zir.Inst.SliceStart, inst_data.payload_index).data;3407 const extra = sema.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data;
2628 const array_ptr = try sema.resolveInst(extra.lhs);3408 const array_ptr = try sema.resolveInst(extra.lhs);
2629 const start = try sema.resolveInst(extra.start);3409 const start = try sema.resolveInst(extra.start);
26303410
2631 return sema.analyzeSlice(block, src, array_ptr, start, null, null, .unneeded);3411 return sema.analyzeSlice(block, src, array_ptr, start, null, null, .unneeded);
2632}3412}
26333413
2634fn zirSliceEnd(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3414fn zirSliceEnd(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2635 const tracy = trace(@src());3415 const tracy = trace(@src());
2636 defer tracy.end();3416 defer tracy.end();
26373417
2638 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3418 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2639 const src = inst_data.src();3419 const src = inst_data.src();
2640 const extra = sema.code.extraData(zir.Inst.SliceEnd, inst_data.payload_index).data;3420 const extra = sema.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data;
2641 const array_ptr = try sema.resolveInst(extra.lhs);3421 const array_ptr = try sema.resolveInst(extra.lhs);
2642 const start = try sema.resolveInst(extra.start);3422 const start = try sema.resolveInst(extra.start);
2643 const end = try sema.resolveInst(extra.end);3423 const end = try sema.resolveInst(extra.end);
...@@ -2645,14 +3425,14 @@ fn zirSliceEnd(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro...@@ -2645,14 +3425,14 @@ fn zirSliceEnd(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
2645 return sema.analyzeSlice(block, src, array_ptr, start, end, null, .unneeded);3425 return sema.analyzeSlice(block, src, array_ptr, start, end, null, .unneeded);
2646}3426}
26473427
2648fn zirSliceSentinel(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3428fn zirSliceSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2649 const tracy = trace(@src());3429 const tracy = trace(@src());
2650 defer tracy.end();3430 defer tracy.end();
26513431
2652 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3432 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2653 const src = inst_data.src();3433 const src = inst_data.src();
2654 const sentinel_src: LazySrcLoc = .{ .node_offset_slice_sentinel = inst_data.src_node };3434 const sentinel_src: LazySrcLoc = .{ .node_offset_slice_sentinel = inst_data.src_node };
2655 const extra = sema.code.extraData(zir.Inst.SliceSentinel, inst_data.payload_index).data;3435 const extra = sema.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data;
2656 const array_ptr = try sema.resolveInst(extra.lhs);3436 const array_ptr = try sema.resolveInst(extra.lhs);
2657 const start = try sema.resolveInst(extra.start);3437 const start = try sema.resolveInst(extra.start);
2658 const end = try sema.resolveInst(extra.end);3438 const end = try sema.resolveInst(extra.end);
...@@ -2664,7 +3444,7 @@ fn zirSliceSentinel(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inne...@@ -2664,7 +3444,7 @@ fn zirSliceSentinel(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inne
2664fn zirSwitchCapture(3444fn zirSwitchCapture(
2665 sema: *Sema,3445 sema: *Sema,
2666 block: *Scope.Block,3446 block: *Scope.Block,
2667 inst: zir.Inst.Index,3447 inst: Zir.Inst.Index,
2668 is_multi: bool,3448 is_multi: bool,
2669 is_ref: bool,3449 is_ref: bool,
2670) InnerError!*Inst {3450) InnerError!*Inst {
...@@ -2682,7 +3462,7 @@ fn zirSwitchCapture(...@@ -2682,7 +3462,7 @@ fn zirSwitchCapture(
2682fn zirSwitchCaptureElse(3462fn zirSwitchCaptureElse(
2683 sema: *Sema,3463 sema: *Sema,
2684 block: *Scope.Block,3464 block: *Scope.Block,
2685 inst: zir.Inst.Index,3465 inst: Zir.Inst.Index,
2686 is_ref: bool,3466 is_ref: bool,
2687) InnerError!*Inst {3467) InnerError!*Inst {
2688 const tracy = trace(@src());3468 const tracy = trace(@src());
...@@ -2699,9 +3479,9 @@ fn zirSwitchCaptureElse(...@@ -2699,9 +3479,9 @@ fn zirSwitchCaptureElse(
2699fn zirSwitchBlock(3479fn zirSwitchBlock(
2700 sema: *Sema,3480 sema: *Sema,
2701 block: *Scope.Block,3481 block: *Scope.Block,
2702 inst: zir.Inst.Index,3482 inst: Zir.Inst.Index,
2703 is_ref: bool,3483 is_ref: bool,
2704 special_prong: zir.SpecialProng,3484 special_prong: Zir.SpecialProng,
2705) InnerError!*Inst {3485) InnerError!*Inst {
2706 const tracy = trace(@src());3486 const tracy = trace(@src());
2707 defer tracy.end();3487 defer tracy.end();
...@@ -2709,7 +3489,7 @@ fn zirSwitchBlock(...@@ -2709,7 +3489,7 @@ fn zirSwitchBlock(
2709 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3489 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2710 const src = inst_data.src();3490 const src = inst_data.src();
2711 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = inst_data.src_node };3491 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = inst_data.src_node };
2712 const extra = sema.code.extraData(zir.Inst.SwitchBlock, inst_data.payload_index);3492 const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);
27133493
2714 const operand_ptr = try sema.resolveInst(extra.data.operand);3494 const operand_ptr = try sema.resolveInst(extra.data.operand);
2715 const operand = if (is_ref)3495 const operand = if (is_ref)
...@@ -2732,9 +3512,9 @@ fn zirSwitchBlock(...@@ -2732,9 +3512,9 @@ fn zirSwitchBlock(
2732fn zirSwitchBlockMulti(3512fn zirSwitchBlockMulti(
2733 sema: *Sema,3513 sema: *Sema,
2734 block: *Scope.Block,3514 block: *Scope.Block,
2735 inst: zir.Inst.Index,3515 inst: Zir.Inst.Index,
2736 is_ref: bool,3516 is_ref: bool,
2737 special_prong: zir.SpecialProng,3517 special_prong: Zir.SpecialProng,
2738) InnerError!*Inst {3518) InnerError!*Inst {
2739 const tracy = trace(@src());3519 const tracy = trace(@src());
2740 defer tracy.end();3520 defer tracy.end();
...@@ -2742,7 +3522,7 @@ fn zirSwitchBlockMulti(...@@ -2742,7 +3522,7 @@ fn zirSwitchBlockMulti(
2742 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;3522 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2743 const src = inst_data.src();3523 const src = inst_data.src();
2744 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = inst_data.src_node };3524 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = inst_data.src_node };
2745 const extra = sema.code.extraData(zir.Inst.SwitchBlockMulti, inst_data.payload_index);3525 const extra = sema.code.extraData(Zir.Inst.SwitchBlockMulti, inst_data.payload_index);
27463526
2747 const operand_ptr = try sema.resolveInst(extra.data.operand);3527 const operand_ptr = try sema.resolveInst(extra.data.operand);
2748 const operand = if (is_ref)3528 const operand = if (is_ref)
...@@ -2767,16 +3547,16 @@ fn analyzeSwitch(...@@ -2767,16 +3547,16 @@ fn analyzeSwitch(
2767 block: *Scope.Block,3547 block: *Scope.Block,
2768 operand: *Inst,3548 operand: *Inst,
2769 extra_end: usize,3549 extra_end: usize,
2770 special_prong: zir.SpecialProng,3550 special_prong: Zir.SpecialProng,
2771 scalar_cases_len: usize,3551 scalar_cases_len: usize,
2772 multi_cases_len: usize,3552 multi_cases_len: usize,
2773 switch_inst: zir.Inst.Index,3553 switch_inst: Zir.Inst.Index,
2774 src_node_offset: i32,3554 src_node_offset: i32,
2775) InnerError!*Inst {3555) InnerError!*Inst {
2776 const gpa = sema.gpa;3556 const gpa = sema.gpa;
2777 const mod = sema.mod;3557 const mod = sema.mod;
27783558
2779 const special: struct { body: []const zir.Inst.Index, end: usize } = switch (special_prong) {3559 const special: struct { body: []const Zir.Inst.Index, end: usize } = switch (special_prong) {
2780 .none => .{ .body = &.{}, .end = extra_end },3560 .none => .{ .body = &.{}, .end = extra_end },
2781 .under, .@"else" => blk: {3561 .under, .@"else" => blk: {
2782 const body_len = sema.code.extra[extra_end];3562 const body_len = sema.code.extra[extra_end];
...@@ -2817,16 +3597,16 @@ fn analyzeSwitch(...@@ -2817,16 +3597,16 @@ fn analyzeSwitch(
2817 // Validate for duplicate items, missing else prong, and invalid range.3597 // Validate for duplicate items, missing else prong, and invalid range.
2818 switch (operand.ty.zigTypeTag()) {3598 switch (operand.ty.zigTypeTag()) {
2819 .Enum => {3599 .Enum => {
2820 var seen_fields = try gpa.alloc(?AstGen.SwitchProngSrc, operand.ty.enumFieldCount());3600 var seen_fields = try gpa.alloc(?Module.SwitchProngSrc, operand.ty.enumFieldCount());
2821 defer gpa.free(seen_fields);3601 defer gpa.free(seen_fields);
28223602
2823 mem.set(?AstGen.SwitchProngSrc, seen_fields, null);3603 mem.set(?Module.SwitchProngSrc, seen_fields, null);
28243604
2825 var extra_index: usize = special.end;3605 var extra_index: usize = special.end;
2826 {3606 {
2827 var scalar_i: u32 = 0;3607 var scalar_i: u32 = 0;
2828 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {3608 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
2829 const item_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);3609 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
2830 extra_index += 1;3610 extra_index += 1;
2831 const body_len = sema.code.extra[extra_index];3611 const body_len = sema.code.extra[extra_index];
2832 extra_index += 1;3612 extra_index += 1;
...@@ -2936,7 +3716,7 @@ fn analyzeSwitch(...@@ -2936,7 +3716,7 @@ fn analyzeSwitch(
2936 {3716 {
2937 var scalar_i: u32 = 0;3717 var scalar_i: u32 = 0;
2938 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {3718 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
2939 const item_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);3719 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
2940 extra_index += 1;3720 extra_index += 1;
2941 const body_len = sema.code.extra[extra_index];3721 const body_len = sema.code.extra[extra_index];
2942 extra_index += 1;3722 extra_index += 1;
...@@ -2976,9 +3756,9 @@ fn analyzeSwitch(...@@ -2976,9 +3756,9 @@ fn analyzeSwitch(
29763756
2977 var range_i: u32 = 0;3757 var range_i: u32 = 0;
2978 while (range_i < ranges_len) : (range_i += 1) {3758 while (range_i < ranges_len) : (range_i += 1) {
2979 const item_first = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);3759 const item_first = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
2980 extra_index += 1;3760 extra_index += 1;
2981 const item_last = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);3761 const item_last = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
2982 extra_index += 1;3762 extra_index += 1;
29833763
2984 try sema.validateSwitchRange(3764 try sema.validateSwitchRange(
...@@ -3032,7 +3812,7 @@ fn analyzeSwitch(...@@ -3032,7 +3812,7 @@ fn analyzeSwitch(
3032 {3812 {
3033 var scalar_i: u32 = 0;3813 var scalar_i: u32 = 0;
3034 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {3814 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
3035 const item_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);3815 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
3036 extra_index += 1;3816 extra_index += 1;
3037 const body_len = sema.code.extra[extra_index];3817 const body_len = sema.code.extra[extra_index];
3038 extra_index += 1;3818 extra_index += 1;
...@@ -3115,7 +3895,7 @@ fn analyzeSwitch(...@@ -3115,7 +3895,7 @@ fn analyzeSwitch(
3115 {3895 {
3116 var scalar_i: u32 = 0;3896 var scalar_i: u32 = 0;
3117 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {3897 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
3118 const item_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);3898 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
3119 extra_index += 1;3899 extra_index += 1;
3120 const body_len = sema.code.extra[extra_index];3900 const body_len = sema.code.extra[extra_index];
3121 extra_index += 1;3901 extra_index += 1;
...@@ -3177,12 +3957,45 @@ fn analyzeSwitch(...@@ -3177,12 +3957,45 @@ fn analyzeSwitch(
3177 }),3957 }),
3178 }3958 }
31793959
3180 if (try sema.resolveDefinedValue(block, src, operand)) |operand_val| {3960 const block_inst = try sema.arena.create(Inst.Block);
3961 block_inst.* = .{
3962 .base = .{
3963 .tag = Inst.Block.base_tag,
3964 .ty = undefined, // Set after analysis.
3965 .src = src,
3966 },
3967 .body = undefined,
3968 };
3969
3970 var label: Scope.Block.Label = .{
3971 .zir_block = switch_inst,
3972 .merges = .{
3973 .results = .{},
3974 .br_list = .{},
3975 .block_inst = block_inst,
3976 },
3977 };
3978
3979 var child_block: Scope.Block = .{
3980 .parent = block,
3981 .sema = sema,
3982 .src_decl = block.src_decl,
3983 .instructions = .{},
3984 .label = &label,
3985 .inlining = block.inlining,
3986 .is_comptime = block.is_comptime,
3987 };
3988 const merges = &child_block.label.?.merges;
3989 defer child_block.instructions.deinit(gpa);
3990 defer merges.results.deinit(gpa);
3991 defer merges.br_list.deinit(gpa);
3992
3993 if (try sema.resolveDefinedValue(&child_block, src, operand)) |operand_val| {
3181 var extra_index: usize = special.end;3994 var extra_index: usize = special.end;
3182 {3995 {
3183 var scalar_i: usize = 0;3996 var scalar_i: usize = 0;
3184 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {3997 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
3185 const item_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);3998 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
3186 extra_index += 1;3999 extra_index += 1;
3187 const body_len = sema.code.extra[extra_index];4000 const body_len = sema.code.extra[extra_index];
3188 extra_index += 1;4001 extra_index += 1;
...@@ -3191,9 +4004,9 @@ fn analyzeSwitch(...@@ -3191,9 +4004,9 @@ fn analyzeSwitch(
31914004
3192 // Validation above ensured these will succeed.4005 // Validation above ensured these will succeed.
3193 const item = sema.resolveInst(item_ref) catch unreachable;4006 const item = sema.resolveInst(item_ref) catch unreachable;
3194 const item_val = sema.resolveConstValue(block, .unneeded, item) catch unreachable;4007 const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable;
3195 if (operand_val.eql(item_val)) {4008 if (operand_val.eql(item_val)) {
3196 return sema.resolveBody(block, body);4009 return sema.resolveBlockBody(block, src, &child_block, body, merges);
3197 }4010 }
3198 }4011 }
3199 }4012 }
...@@ -3213,76 +4026,44 @@ fn analyzeSwitch(...@@ -3213,76 +4026,44 @@ fn analyzeSwitch(
3213 for (items) |item_ref| {4026 for (items) |item_ref| {
3214 // Validation above ensured these will succeed.4027 // Validation above ensured these will succeed.
3215 const item = sema.resolveInst(item_ref) catch unreachable;4028 const item = sema.resolveInst(item_ref) catch unreachable;
3216 const item_val = sema.resolveConstValue(block, item.src, item) catch unreachable;4029 const item_val = sema.resolveConstValue(&child_block, item.src, item) catch unreachable;
3217 if (operand_val.eql(item_val)) {4030 if (operand_val.eql(item_val)) {
3218 return sema.resolveBody(block, body);4031 return sema.resolveBlockBody(block, src, &child_block, body, merges);
3219 }4032 }
3220 }4033 }
32214034
3222 var range_i: usize = 0;4035 var range_i: usize = 0;
3223 while (range_i < ranges_len) : (range_i += 1) {4036 while (range_i < ranges_len) : (range_i += 1) {
3224 const item_first = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);4037 const item_first = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
3225 extra_index += 1;4038 extra_index += 1;
3226 const item_last = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);4039 const item_last = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
3227 extra_index += 1;4040 extra_index += 1;
32284041
3229 // Validation above ensured these will succeed.4042 // Validation above ensured these will succeed.
3230 const first_tv = sema.resolveInstConst(block, .unneeded, item_first) catch unreachable;4043 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first) catch unreachable;
3231 const last_tv = sema.resolveInstConst(block, .unneeded, item_last) catch unreachable;4044 const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last) catch unreachable;
3232 if (Value.compare(operand_val, .gte, first_tv.val) and4045 if (Value.compare(operand_val, .gte, first_tv.val) and
3233 Value.compare(operand_val, .lte, last_tv.val))4046 Value.compare(operand_val, .lte, last_tv.val))
3234 {4047 {
3235 return sema.resolveBody(block, body);4048 return sema.resolveBlockBody(block, src, &child_block, body, merges);
3236 }4049 }
3237 }4050 }
32384051
3239 extra_index += body_len;4052 extra_index += body_len;
3240 }4053 }
3241 }4054 }
3242 return sema.resolveBody(block, special.body);4055 return sema.resolveBlockBody(block, src, &child_block, special.body, merges);
3243 }4056 }
32444057
3245 if (scalar_cases_len + multi_cases_len == 0) {4058 if (scalar_cases_len + multi_cases_len == 0) {
3246 return sema.resolveBody(block, special.body);4059 return sema.resolveBlockBody(block, src, &child_block, special.body, merges);
3247 }4060 }
32484061
3249 try sema.requireRuntimeBlock(block, src);4062 try sema.requireRuntimeBlock(block, src);
32504063
3251 const block_inst = try sema.arena.create(Inst.Block);4064 // TODO when reworking AIR memory layout make multi cases get generated as cases,
3252 block_inst.* = .{4065 // not as part of the "else" block.
3253 .base = .{4066 const cases = try sema.arena.alloc(Inst.SwitchBr.Case, scalar_cases_len);
3254 .tag = Inst.Block.base_tag,
3255 .ty = undefined, // Set after analysis.
3256 .src = src,
3257 },
3258 .body = undefined,
3259 };
3260
3261 var child_block: Scope.Block = .{
3262 .parent = block,
3263 .sema = sema,
3264 .src_decl = block.src_decl,
3265 .instructions = .{},
3266 // TODO @as here is working around a stage1 miscompilation bug :(
3267 .label = @as(?Scope.Block.Label, Scope.Block.Label{
3268 .zir_block = switch_inst,
3269 .merges = .{
3270 .results = .{},
3271 .br_list = .{},
3272 .block_inst = block_inst,
3273 },
3274 }),
3275 .inlining = block.inlining,
3276 .is_comptime = block.is_comptime,
3277 };
3278 const merges = &child_block.label.?.merges;
3279 defer child_block.instructions.deinit(gpa);
3280 defer merges.results.deinit(gpa);
3281 defer merges.br_list.deinit(gpa);
3282
3283 // TODO when reworking TZIR memory layout make multi cases get generated as cases,
3284 // not as part of the "else" block.
3285 const cases = try sema.arena.alloc(Inst.SwitchBr.Case, scalar_cases_len);
32864067
3287 var case_block = child_block.makeSubBlock();4068 var case_block = child_block.makeSubBlock();
3288 defer case_block.instructions.deinit(gpa);4069 defer case_block.instructions.deinit(gpa);
...@@ -3291,7 +4072,7 @@ fn analyzeSwitch(...@@ -3291,7 +4072,7 @@ fn analyzeSwitch(
32914072
3292 var scalar_i: usize = 0;4073 var scalar_i: usize = 0;
3293 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {4074 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
3294 const item_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);4075 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
3295 extra_index += 1;4076 extra_index += 1;
3296 const body_len = sema.code.extra[extra_index];4077 const body_len = sema.code.extra[extra_index];
3297 extra_index += 1;4078 extra_index += 1;
...@@ -3344,9 +4125,9 @@ fn analyzeSwitch(...@@ -3344,9 +4125,9 @@ fn analyzeSwitch(
33444125
3345 var range_i: usize = 0;4126 var range_i: usize = 0;
3346 while (range_i < ranges_len) : (range_i += 1) {4127 while (range_i < ranges_len) : (range_i += 1) {
3347 const first_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);4128 const first_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
3348 extra_index += 1;4129 extra_index += 1;
3349 const last_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);4130 const last_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
3350 extra_index += 1;4131 extra_index += 1;
33514132
3352 const item_first = try sema.resolveInst(first_ref);4133 const item_first = try sema.resolveInst(first_ref);
...@@ -3443,10 +4224,10 @@ fn analyzeSwitch(...@@ -3443,10 +4224,10 @@ fn analyzeSwitch(
3443fn resolveSwitchItemVal(4224fn resolveSwitchItemVal(
3444 sema: *Sema,4225 sema: *Sema,
3445 block: *Scope.Block,4226 block: *Scope.Block,
3446 item_ref: zir.Inst.Ref,4227 item_ref: Zir.Inst.Ref,
3447 switch_node_offset: i32,4228 switch_node_offset: i32,
3448 switch_prong_src: AstGen.SwitchProngSrc,4229 switch_prong_src: Module.SwitchProngSrc,
3449 range_expand: AstGen.SwitchProngSrc.RangeExpand,4230 range_expand: Module.SwitchProngSrc.RangeExpand,
3450) InnerError!TypedValue {4231) InnerError!TypedValue {
3451 const item = try sema.resolveInst(item_ref);4232 const item = try sema.resolveInst(item_ref);
3452 // We have to avoid the other helper functions here because we cannot construct a LazySrcLoc4233 // We have to avoid the other helper functions here because we cannot construct a LazySrcLoc
...@@ -3454,12 +4235,12 @@ fn resolveSwitchItemVal(...@@ -3454,12 +4235,12 @@ fn resolveSwitchItemVal(
3454 // a compile error do we resolve the full source locations.4235 // a compile error do we resolve the full source locations.
3455 if (item.value()) |val| {4236 if (item.value()) |val| {
3456 if (val.isUndef()) {4237 if (val.isUndef()) {
3457 const src = switch_prong_src.resolve(block.src_decl, switch_node_offset, range_expand);4238 const src = switch_prong_src.resolve(sema.gpa, block.src_decl, switch_node_offset, range_expand);
3458 return sema.failWithUseOfUndef(block, src);4239 return sema.failWithUseOfUndef(block, src);
3459 }4240 }
3460 return TypedValue{ .ty = item.ty, .val = val };4241 return TypedValue{ .ty = item.ty, .val = val };
3461 }4242 }
3462 const src = switch_prong_src.resolve(block.src_decl, switch_node_offset, range_expand);4243 const src = switch_prong_src.resolve(sema.gpa, block.src_decl, switch_node_offset, range_expand);
3463 return sema.failWithNeededComptime(block, src);4244 return sema.failWithNeededComptime(block, src);
3464}4245}
34654246
...@@ -3467,10 +4248,10 @@ fn validateSwitchRange(...@@ -3467,10 +4248,10 @@ fn validateSwitchRange(
3467 sema: *Sema,4248 sema: *Sema,
3468 block: *Scope.Block,4249 block: *Scope.Block,
3469 range_set: *RangeSet,4250 range_set: *RangeSet,
3470 first_ref: zir.Inst.Ref,4251 first_ref: Zir.Inst.Ref,
3471 last_ref: zir.Inst.Ref,4252 last_ref: Zir.Inst.Ref,
3472 src_node_offset: i32,4253 src_node_offset: i32,
3473 switch_prong_src: AstGen.SwitchProngSrc,4254 switch_prong_src: Module.SwitchProngSrc,
3474) InnerError!void {4255) InnerError!void {
3475 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;4256 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;
3476 const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;4257 const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;
...@@ -3482,9 +4263,9 @@ fn validateSwitchItem(...@@ -3482,9 +4263,9 @@ fn validateSwitchItem(
3482 sema: *Sema,4263 sema: *Sema,
3483 block: *Scope.Block,4264 block: *Scope.Block,
3484 range_set: *RangeSet,4265 range_set: *RangeSet,
3485 item_ref: zir.Inst.Ref,4266 item_ref: Zir.Inst.Ref,
3486 src_node_offset: i32,4267 src_node_offset: i32,
3487 switch_prong_src: AstGen.SwitchProngSrc,4268 switch_prong_src: Module.SwitchProngSrc,
3488) InnerError!void {4269) InnerError!void {
3489 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;4270 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
3490 const maybe_prev_src = try range_set.add(item_val, item_val, switch_prong_src);4271 const maybe_prev_src = try range_set.add(item_val, item_val, switch_prong_src);
...@@ -3494,16 +4275,16 @@ fn validateSwitchItem(...@@ -3494,16 +4275,16 @@ fn validateSwitchItem(
3494fn validateSwitchItemEnum(4275fn validateSwitchItemEnum(
3495 sema: *Sema,4276 sema: *Sema,
3496 block: *Scope.Block,4277 block: *Scope.Block,
3497 seen_fields: []?AstGen.SwitchProngSrc,4278 seen_fields: []?Module.SwitchProngSrc,
3498 item_ref: zir.Inst.Ref,4279 item_ref: Zir.Inst.Ref,
3499 src_node_offset: i32,4280 src_node_offset: i32,
3500 switch_prong_src: AstGen.SwitchProngSrc,4281 switch_prong_src: Module.SwitchProngSrc,
3501) InnerError!void {4282) InnerError!void {
3502 const mod = sema.mod;4283 const mod = sema.mod;
3503 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);4284 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
3504 const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val) orelse {4285 const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val) orelse {
3505 const msg = msg: {4286 const msg = msg: {
3506 const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .none);4287 const src = switch_prong_src.resolve(sema.gpa, block.src_decl, src_node_offset, .none);
3507 const msg = try mod.errMsg(4288 const msg = try mod.errMsg(
3508 &block.base,4289 &block.base,
3509 src,4290 src,
...@@ -3529,14 +4310,15 @@ fn validateSwitchItemEnum(...@@ -3529,14 +4310,15 @@ fn validateSwitchItemEnum(
3529fn validateSwitchDupe(4310fn validateSwitchDupe(
3530 sema: *Sema,4311 sema: *Sema,
3531 block: *Scope.Block,4312 block: *Scope.Block,
3532 maybe_prev_src: ?AstGen.SwitchProngSrc,4313 maybe_prev_src: ?Module.SwitchProngSrc,
3533 switch_prong_src: AstGen.SwitchProngSrc,4314 switch_prong_src: Module.SwitchProngSrc,
3534 src_node_offset: i32,4315 src_node_offset: i32,
3535) InnerError!void {4316) InnerError!void {
3536 const prev_prong_src = maybe_prev_src orelse return;4317 const prev_prong_src = maybe_prev_src orelse return;
3537 const mod = sema.mod;4318 const mod = sema.mod;
3538 const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .none);4319 const gpa = sema.gpa;
3539 const prev_src = prev_prong_src.resolve(block.src_decl, src_node_offset, .none);4320 const src = switch_prong_src.resolve(gpa, block.src_decl, src_node_offset, .none);
4321 const prev_src = prev_prong_src.resolve(gpa, block.src_decl, src_node_offset, .none);
3540 const msg = msg: {4322 const msg = msg: {
3541 const msg = try mod.errMsg(4323 const msg = try mod.errMsg(
3542 &block.base,4324 &block.base,
...@@ -3562,9 +4344,9 @@ fn validateSwitchItemBool(...@@ -3562,9 +4344,9 @@ fn validateSwitchItemBool(
3562 block: *Scope.Block,4344 block: *Scope.Block,
3563 true_count: *u8,4345 true_count: *u8,
3564 false_count: *u8,4346 false_count: *u8,
3565 item_ref: zir.Inst.Ref,4347 item_ref: Zir.Inst.Ref,
3566 src_node_offset: i32,4348 src_node_offset: i32,
3567 switch_prong_src: AstGen.SwitchProngSrc,4349 switch_prong_src: Module.SwitchProngSrc,
3568) InnerError!void {4350) InnerError!void {
3569 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;4351 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
3570 if (item_val.toBool()) {4352 if (item_val.toBool()) {
...@@ -3573,20 +4355,20 @@ fn validateSwitchItemBool(...@@ -3573,20 +4355,20 @@ fn validateSwitchItemBool(
3573 false_count.* += 1;4355 false_count.* += 1;
3574 }4356 }
3575 if (true_count.* + false_count.* > 2) {4357 if (true_count.* + false_count.* > 2) {
3576 const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .none);4358 const src = switch_prong_src.resolve(sema.gpa, block.src_decl, src_node_offset, .none);
3577 return sema.mod.fail(&block.base, src, "duplicate switch value", .{});4359 return sema.mod.fail(&block.base, src, "duplicate switch value", .{});
3578 }4360 }
3579}4361}
35804362
3581const ValueSrcMap = std.HashMap(Value, AstGen.SwitchProngSrc, Value.hash, Value.eql, std.hash_map.DefaultMaxLoadPercentage);4363const ValueSrcMap = std.HashMap(Value, Module.SwitchProngSrc, Value.hash, Value.eql, std.hash_map.DefaultMaxLoadPercentage);
35824364
3583fn validateSwitchItemSparse(4365fn validateSwitchItemSparse(
3584 sema: *Sema,4366 sema: *Sema,
3585 block: *Scope.Block,4367 block: *Scope.Block,
3586 seen_values: *ValueSrcMap,4368 seen_values: *ValueSrcMap,
3587 item_ref: zir.Inst.Ref,4369 item_ref: Zir.Inst.Ref,
3588 src_node_offset: i32,4370 src_node_offset: i32,
3589 switch_prong_src: AstGen.SwitchProngSrc,4371 switch_prong_src: Module.SwitchProngSrc,
3590) InnerError!void {4372) InnerError!void {
3591 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;4373 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
3592 const entry = (try seen_values.fetchPut(item_val, switch_prong_src)) orelse return;4374 const entry = (try seen_values.fetchPut(item_val, switch_prong_src)) orelse return;
...@@ -3626,12 +4408,17 @@ fn validateSwitchNoRange(...@@ -3626,12 +4408,17 @@ fn validateSwitchNoRange(
3626 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);4408 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
3627}4409}
36284410
3629fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {4411fn zirHasField(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
3630 const tracy = trace(@src());4412 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
3631 defer tracy.end();4413 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
4414 const src = inst_data.src();
4415
4416 return sema.mod.fail(&block.base, src, "TODO implement zirHasField", .{});
4417}
36324418
4419fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
3633 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;4420 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
3634 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;4421 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
3635 const src = inst_data.src();4422 const src = inst_data.src();
3636 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };4423 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
3637 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };4424 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
...@@ -3640,51 +4427,52 @@ fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -3640,51 +4427,52 @@ fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
3640 const mod = sema.mod;4427 const mod = sema.mod;
3641 const arena = sema.arena;4428 const arena = sema.arena;
36424429
3643 const container_scope = container_type.getContainerScope() orelse return mod.fail(4430 const namespace = container_type.getNamespace() orelse return mod.fail(
3644 &block.base,4431 &block.base,
3645 lhs_src,4432 lhs_src,
3646 "expected struct, enum, union, or opaque, found '{}'",4433 "expected struct, enum, union, or opaque, found '{}'",
3647 .{container_type},4434 .{container_type},
3648 );4435 );
3649 if (mod.lookupDeclName(&container_scope.base, decl_name)) |decl| {4436 if (try sema.lookupInNamespace(namespace, decl_name)) |decl| {
3650 // TODO if !decl.is_pub and inDifferentFiles() return false4437 if (decl.is_pub or decl.namespace.file_scope == block.base.namespace().file_scope) {
3651 return mod.constBool(arena, src, true);4438 return mod.constBool(arena, src, true);
3652 } else {4439 }
3653 return mod.constBool(arena, src, false);
3654 }4440 }
4441 return mod.constBool(arena, src, false);
3655}4442}
36564443
3657fn zirImport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {4444fn zirImport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
3658 const tracy = trace(@src());4445 const tracy = trace(@src());
3659 defer tracy.end();4446 defer tracy.end();
36604447
3661 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4448 const mod = sema.mod;
4449 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
3662 const src = inst_data.src();4450 const src = inst_data.src();
3663 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };4451 const operand = inst_data.get(sema.code);
3664 const operand = try sema.resolveConstString(block, operand_src, inst_data.operand);
36654452
3666 const file_scope = sema.analyzeImport(block, src, operand) catch |err| switch (err) {4453 const result = mod.importFile(block.getFileScope(), operand) catch |err| switch (err) {
3667 error.ImportOutsidePkgPath => {4454 error.ImportOutsidePkgPath => {
3668 return sema.mod.fail(&block.base, src, "import of file outside package path: '{s}'", .{operand});4455 return mod.fail(&block.base, src, "import of file outside package path: '{s}'", .{operand});
3669 },
3670 error.FileNotFound => {
3671 return sema.mod.fail(&block.base, src, "unable to find '{s}'", .{operand});
3672 },4456 },
3673 else => {4457 else => {
3674 // TODO: make sure this gets retried and not cached4458 // TODO: these errors are file system errors; make sure an update() will
3675 return sema.mod.fail(&block.base, src, "unable to open '{s}': {s}", .{ operand, @errorName(err) });4459 // retry this and not cache the file system error, which may be transient.
4460 return mod.fail(&block.base, src, "unable to open '{s}': {s}", .{ operand, @errorName(err) });
3676 },4461 },
3677 };4462 };
3678 return sema.mod.constType(sema.arena, src, file_scope.root_container.ty);4463 try mod.semaFile(result.file);
4464 const file_root_decl = result.file.root_decl.?;
4465 try sema.mod.declareDeclDependency(sema.owner_decl, file_root_decl);
4466 return mod.constType(sema.arena, src, file_root_decl.ty);
3679}4467}
36804468
3681fn zirShl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {4469fn zirShl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
3682 const tracy = trace(@src());4470 const tracy = trace(@src());
3683 defer tracy.end();4471 defer tracy.end();
3684 return sema.mod.fail(&block.base, sema.src, "TODO implement zirShl", .{});4472 return sema.mod.fail(&block.base, sema.src, "TODO implement zirShl", .{});
3685}4473}
36864474
3687fn zirShr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {4475fn zirShr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
3688 const tracy = trace(@src());4476 const tracy = trace(@src());
3689 defer tracy.end();4477 defer tracy.end();
3690 return sema.mod.fail(&block.base, sema.src, "TODO implement zirShr", .{});4478 return sema.mod.fail(&block.base, sema.src, "TODO implement zirShr", .{});
...@@ -3693,7 +4481,7 @@ fn zirShr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In...@@ -3693,7 +4481,7 @@ fn zirShr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In
3693fn zirBitwise(4481fn zirBitwise(
3694 sema: *Sema,4482 sema: *Sema,
3695 block: *Scope.Block,4483 block: *Scope.Block,
3696 inst: zir.Inst.Index,4484 inst: Zir.Inst.Index,
3697 ir_tag: ir.Inst.Tag,4485 ir_tag: ir.Inst.Tag,
3698) InnerError!*Inst {4486) InnerError!*Inst {
3699 const tracy = trace(@src());4487 const tracy = trace(@src());
...@@ -3703,7 +4491,7 @@ fn zirBitwise(...@@ -3703,7 +4491,7 @@ fn zirBitwise(
3703 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };4491 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
3704 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };4492 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
3705 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };4493 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
3706 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;4494 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
3707 const lhs = try sema.resolveInst(extra.lhs);4495 const lhs = try sema.resolveInst(extra.lhs);
3708 const rhs = try sema.resolveInst(extra.rhs);4496 const rhs = try sema.resolveInst(extra.rhs);
37094497
...@@ -3743,10 +4531,7 @@ fn zirBitwise(...@@ -3743,10 +4531,7 @@ fn zirBitwise(
3743 if (casted_lhs.value()) |lhs_val| {4531 if (casted_lhs.value()) |lhs_val| {
3744 if (casted_rhs.value()) |rhs_val| {4532 if (casted_rhs.value()) |rhs_val| {
3745 if (lhs_val.isUndef() or rhs_val.isUndef()) {4533 if (lhs_val.isUndef() or rhs_val.isUndef()) {
3746 return sema.mod.constInst(sema.arena, src, .{4534 return sema.mod.constUndef(sema.arena, src, resolved_type);
3747 .ty = resolved_type,
3748 .val = Value.initTag(.undef),
3749 });
3750 }4535 }
3751 return sema.mod.fail(&block.base, src, "TODO implement comptime bitwise operations", .{});4536 return sema.mod.fail(&block.base, src, "TODO implement comptime bitwise operations", .{});
3752 }4537 }
...@@ -3756,19 +4541,19 @@ fn zirBitwise(...@@ -3756,19 +4541,19 @@ fn zirBitwise(
3756 return block.addBinOp(src, scalar_type, ir_tag, casted_lhs, casted_rhs);4541 return block.addBinOp(src, scalar_type, ir_tag, casted_lhs, casted_rhs);
3757}4542}
37584543
3759fn zirBitNot(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {4544fn zirBitNot(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
3760 const tracy = trace(@src());4545 const tracy = trace(@src());
3761 defer tracy.end();4546 defer tracy.end();
3762 return sema.mod.fail(&block.base, sema.src, "TODO implement zirBitNot", .{});4547 return sema.mod.fail(&block.base, sema.src, "TODO implement zirBitNot", .{});
3763}4548}
37644549
3765fn zirArrayCat(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {4550fn zirArrayCat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
3766 const tracy = trace(@src());4551 const tracy = trace(@src());
3767 defer tracy.end();4552 defer tracy.end();
3768 return sema.mod.fail(&block.base, sema.src, "TODO implement zirArrayCat", .{});4553 return sema.mod.fail(&block.base, sema.src, "TODO implement zirArrayCat", .{});
3769}4554}
37704555
3771fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {4556fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
3772 const tracy = trace(@src());4557 const tracy = trace(@src());
3773 defer tracy.end();4558 defer tracy.end();
3774 return sema.mod.fail(&block.base, sema.src, "TODO implement zirArrayMul", .{});4559 return sema.mod.fail(&block.base, sema.src, "TODO implement zirArrayMul", .{});
...@@ -3777,8 +4562,8 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro...@@ -3777,8 +4562,8 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
3777fn zirNegate(4562fn zirNegate(
3778 sema: *Sema,4563 sema: *Sema,
3779 block: *Scope.Block,4564 block: *Scope.Block,
3780 inst: zir.Inst.Index,4565 inst: Zir.Inst.Index,
3781 tag_override: zir.Inst.Tag,4566 tag_override: Zir.Inst.Tag,
3782) InnerError!*Inst {4567) InnerError!*Inst {
3783 const tracy = trace(@src());4568 const tracy = trace(@src());
3784 defer tracy.end();4569 defer tracy.end();
...@@ -3793,7 +4578,7 @@ fn zirNegate(...@@ -3793,7 +4578,7 @@ fn zirNegate(
3793 return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src);4578 return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src);
3794}4579}
37954580
3796fn zirArithmetic(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {4581fn zirArithmetic(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
3797 const tracy = trace(@src());4582 const tracy = trace(@src());
3798 defer tracy.end();4583 defer tracy.end();
37994584
...@@ -3802,17 +4587,31 @@ fn zirArithmetic(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr...@@ -3802,17 +4587,31 @@ fn zirArithmetic(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
3802 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };4587 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
3803 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };4588 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
3804 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };4589 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
3805 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;4590 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
3806 const lhs = try sema.resolveInst(extra.lhs);4591 const lhs = try sema.resolveInst(extra.lhs);
3807 const rhs = try sema.resolveInst(extra.rhs);4592 const rhs = try sema.resolveInst(extra.rhs);
38084593
3809 return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src);4594 return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src);
3810}4595}
38114596
4597fn zirOverflowArithmetic(
4598 sema: *Sema,
4599 block: *Scope.Block,
4600 extended: Zir.Inst.Extended.InstData,
4601) InnerError!*Inst {
4602 const tracy = trace(@src());
4603 defer tracy.end();
4604
4605 const extra = sema.code.extraData(Zir.Inst.OverflowArithmetic, extended.operand).data;
4606 const src: LazySrcLoc = .{ .node_offset = extra.node };
4607
4608 return sema.mod.fail(&block.base, src, "TODO implement Sema.zirOverflowArithmetic", .{});
4609}
4610
3812fn analyzeArithmetic(4611fn analyzeArithmetic(
3813 sema: *Sema,4612 sema: *Sema,
3814 block: *Scope.Block,4613 block: *Scope.Block,
3815 zir_tag: zir.Inst.Tag,4614 zir_tag: Zir.Inst.Tag,
3816 lhs: *Inst,4615 lhs: *Inst,
3817 rhs: *Inst,4616 rhs: *Inst,
3818 src: LazySrcLoc,4617 src: LazySrcLoc,
...@@ -3856,10 +4655,7 @@ fn analyzeArithmetic(...@@ -3856,10 +4655,7 @@ fn analyzeArithmetic(
3856 if (casted_lhs.value()) |lhs_val| {4655 if (casted_lhs.value()) |lhs_val| {
3857 if (casted_rhs.value()) |rhs_val| {4656 if (casted_rhs.value()) |rhs_val| {
3858 if (lhs_val.isUndef() or rhs_val.isUndef()) {4657 if (lhs_val.isUndef() or rhs_val.isUndef()) {
3859 return sema.mod.constInst(sema.arena, src, .{4658 return sema.mod.constUndef(sema.arena, src, resolved_type);
3860 .ty = resolved_type,
3861 .val = Value.initTag(.undef),
3862 });
3863 }4659 }
3864 // incase rhs is 0, simply return lhs without doing any calculations4660 // incase rhs is 0, simply return lhs without doing any calculations
3865 // TODO Once division is implemented we should throw an error when dividing by 0.4661 // TODO Once division is implemented we should throw an error when dividing by 0.
...@@ -3890,6 +4686,13 @@ fn analyzeArithmetic(...@@ -3890,6 +4686,13 @@ fn analyzeArithmetic(
3890 try Module.floatSub(sema.arena, scalar_type, src, lhs_val, rhs_val);4686 try Module.floatSub(sema.arena, scalar_type, src, lhs_val, rhs_val);
3891 break :blk val;4687 break :blk val;
3892 },4688 },
4689 .div => blk: {
4690 const val = if (is_int)
4691 try Module.intDiv(sema.arena, lhs_val, rhs_val)
4692 else
4693 try Module.floatDiv(sema.arena, scalar_type, src, lhs_val, rhs_val);
4694 break :blk val;
4695 },
3893 .mul => blk: {4696 .mul => blk: {
3894 const val = if (is_int)4697 const val = if (is_int)
3895 try Module.intMul(sema.arena, lhs_val, rhs_val)4698 try Module.intMul(sema.arena, lhs_val, rhs_val)
...@@ -3924,7 +4727,7 @@ fn analyzeArithmetic(...@@ -3924,7 +4727,7 @@ fn analyzeArithmetic(
3924 return block.addBinOp(src, scalar_type, ir_tag, casted_lhs, casted_rhs);4727 return block.addBinOp(src, scalar_type, ir_tag, casted_lhs, casted_rhs);
3925}4728}
39264729
3927fn zirLoad(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {4730fn zirLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
3928 const tracy = trace(@src());4731 const tracy = trace(@src());
3929 defer tracy.end();4732 defer tracy.end();
39304733
...@@ -3938,72 +4741,90 @@ fn zirLoad(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*I...@@ -3938,72 +4741,90 @@ fn zirLoad(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*I
3938fn zirAsm(4741fn zirAsm(
3939 sema: *Sema,4742 sema: *Sema,
3940 block: *Scope.Block,4743 block: *Scope.Block,
3941 inst: zir.Inst.Index,4744 extended: Zir.Inst.Extended.InstData,
3942 is_volatile: bool,
3943) InnerError!*Inst {4745) InnerError!*Inst {
3944 const tracy = trace(@src());4746 const tracy = trace(@src());
3945 defer tracy.end();4747 defer tracy.end();
39464748
3947 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;4749 const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand);
3948 const src = inst_data.src();4750 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
3949 const asm_source_src: LazySrcLoc = .{ .node_offset_asm_source = inst_data.src_node };4751 const asm_source_src: LazySrcLoc = .{ .node_offset_asm_source = extra.data.src_node };
3950 const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = inst_data.src_node };4752 const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = extra.data.src_node };
3951 const extra = sema.code.extraData(zir.Inst.Asm, inst_data.payload_index);
3952 const return_type = try sema.resolveType(block, ret_ty_src, extra.data.return_type);
3953 const asm_source = try sema.resolveConstString(block, asm_source_src, extra.data.asm_source);4753 const asm_source = try sema.resolveConstString(block, asm_source_src, extra.data.asm_source);
4754 const outputs_len = @truncate(u5, extended.small);
4755 const inputs_len = @truncate(u5, extended.small >> 5);
4756 const clobbers_len = @truncate(u5, extended.small >> 10);
4757 const is_volatile = @truncate(u1, extended.small >> 15) != 0;
4758
4759 if (outputs_len > 1) {
4760 return sema.mod.fail(&block.base, src, "TODO implement Sema for asm with more than 1 output", .{});
4761 }
39544762
3955 var extra_i = extra.end;4763 var extra_i = extra.end;
3956 const Output = struct { name: []const u8, inst: *Inst };4764 var output_type_bits = extra.data.output_type_bits;
3957 const output: ?Output = if (extra.data.output != .none) blk: {4765
3958 const name = sema.code.nullTerminatedString(sema.code.extra[extra_i]);4766 const Output = struct { constraint: []const u8, ty: Type };
3959 extra_i += 1;4767 const output: ?Output = if (outputs_len == 0) null else blk: {
4768 const output = sema.code.extraData(Zir.Inst.Asm.Output, extra_i);
4769 extra_i = output.end;
4770
4771 const is_type = @truncate(u1, output_type_bits) != 0;
4772 output_type_bits >>= 1;
4773
4774 if (!is_type) {
4775 return sema.mod.fail(&block.base, src, "TODO implement Sema for asm with non `->` output", .{});
4776 }
4777
4778 const constraint = sema.code.nullTerminatedString(output.data.constraint);
3960 break :blk Output{4779 break :blk Output{
3961 .name = name,4780 .constraint = constraint,
3962 .inst = try sema.resolveInst(extra.data.output),4781 .ty = try sema.resolveType(block, ret_ty_src, output.data.operand),
3963 };4782 };
3964 } else null;4783 };
39654784
3966 const args = try sema.arena.alloc(*Inst, extra.data.args_len);4785 const args = try sema.arena.alloc(*Inst, inputs_len);
3967 const inputs = try sema.arena.alloc([]const u8, extra.data.args_len);4786 const inputs = try sema.arena.alloc([]const u8, inputs_len);
3968 const clobbers = try sema.arena.alloc([]const u8, extra.data.clobbers_len);
39694787
3970 for (args) |*arg| {4788 for (args) |*arg, arg_i| {
3971 arg.* = try sema.resolveInst(@intToEnum(zir.Inst.Ref, sema.code.extra[extra_i]));4789 const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i);
3972 extra_i += 1;4790 extra_i = input.end;
3973 }4791
3974 for (inputs) |*name| {4792 const name = sema.code.nullTerminatedString(input.data.name);
3975 name.* = sema.code.nullTerminatedString(sema.code.extra[extra_i]);4793 _ = name; // TODO: use the name
3976 extra_i += 1;4794
4795 arg.* = try sema.resolveInst(input.data.operand);
4796 inputs[arg_i] = sema.code.nullTerminatedString(input.data.constraint);
3977 }4797 }
4798
4799 const clobbers = try sema.arena.alloc([]const u8, clobbers_len);
3978 for (clobbers) |*name| {4800 for (clobbers) |*name| {
3979 name.* = sema.code.nullTerminatedString(sema.code.extra[extra_i]);4801 name.* = sema.code.nullTerminatedString(sema.code.extra[extra_i]);
3980 extra_i += 1;4802 extra_i += 1;
3981 }4803 }
39824804
3983 try sema.requireRuntimeBlock(block, src);4805 try sema.requireRuntimeBlock(block, src);
3984 const asm_tzir = try sema.arena.create(Inst.Assembly);4806 const asm_air = try sema.arena.create(Inst.Assembly);
3985 asm_tzir.* = .{4807 asm_air.* = .{
3986 .base = .{4808 .base = .{
3987 .tag = .assembly,4809 .tag = .assembly,
3988 .ty = return_type,4810 .ty = if (output) |o| o.ty else Type.initTag(.void),
3989 .src = src,4811 .src = src,
3990 },4812 },
3991 .asm_source = asm_source,4813 .asm_source = asm_source,
3992 .is_volatile = is_volatile,4814 .is_volatile = is_volatile,
3993 .output = if (output) |o| o.inst else null,4815 .output_constraint = if (output) |o| o.constraint else null,
3994 .output_name = if (output) |o| o.name else null,
3995 .inputs = inputs,4816 .inputs = inputs,
3996 .clobbers = clobbers,4817 .clobbers = clobbers,
3997 .args = args,4818 .args = args,
3998 };4819 };
3999 try block.instructions.append(sema.gpa, &asm_tzir.base);4820 try block.instructions.append(sema.gpa, &asm_air.base);
4000 return &asm_tzir.base;4821 return &asm_air.base;
4001}4822}
40024823
4003fn zirCmp(4824fn zirCmp(
4004 sema: *Sema,4825 sema: *Sema,
4005 block: *Scope.Block,4826 block: *Scope.Block,
4006 inst: zir.Inst.Index,4827 inst: Zir.Inst.Index,
4007 op: std.math.CompareOperator,4828 op: std.math.CompareOperator,
4008) InnerError!*Inst {4829) InnerError!*Inst {
4009 const tracy = trace(@src());4830 const tracy = trace(@src());
...@@ -4012,7 +4833,7 @@ fn zirCmp(...@@ -4012,7 +4833,7 @@ fn zirCmp(
4012 const mod = sema.mod;4833 const mod = sema.mod;
40134834
4014 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;4835 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
4015 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;4836 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
4016 const src: LazySrcLoc = inst_data.src();4837 const src: LazySrcLoc = inst_data.src();
4017 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };4838 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
4018 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };4839 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
...@@ -4079,8 +4900,18 @@ fn zirCmp(...@@ -4079,8 +4900,18 @@ fn zirCmp(
40794900
4080 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);4901 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
4081 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);4902 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
4082 try sema.requireRuntimeBlock(block, src); // TODO try to do it at comptime4903
4083 const bool_type = Type.initTag(.bool); // TODO handle vectors4904 if (casted_lhs.value()) |lhs_val| {
4905 if (casted_rhs.value()) |rhs_val| {
4906 if (lhs_val.isUndef() or rhs_val.isUndef()) {
4907 return sema.mod.constUndef(sema.arena, src, resolved_type);
4908 }
4909 const result = lhs_val.compare(op, rhs_val);
4910 return sema.mod.constBool(sema.arena, src, result);
4911 }
4912 }
4913
4914 try sema.requireRuntimeBlock(block, src);
4084 const tag: Inst.Tag = switch (op) {4915 const tag: Inst.Tag = switch (op) {
4085 .lt => .cmp_lt,4916 .lt => .cmp_lt,
4086 .lte => .cmp_lte,4917 .lte => .cmp_lte,
...@@ -4089,23 +4920,109 @@ fn zirCmp(...@@ -4089,23 +4920,109 @@ fn zirCmp(
4089 .gt => .cmp_gt,4920 .gt => .cmp_gt,
4090 .neq => .cmp_neq,4921 .neq => .cmp_neq,
4091 };4922 };
4923 const bool_type = Type.initTag(.bool); // TODO handle vectors
4092 return block.addBinOp(src, bool_type, tag, casted_lhs, casted_rhs);4924 return block.addBinOp(src, bool_type, tag, casted_lhs, casted_rhs);
4093}4925}
40944926
4095fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {4927fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
4096 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4928 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4097 const src = inst_data.src();4929 const src = inst_data.src();
4098 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirTypeInfo", .{});4930 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
4931 const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
4932 const target = sema.mod.getTarget();
4933 const abi_size = operand_ty.abiSize(target);
4934 return sema.mod.constIntUnsigned(sema.arena, src, Type.initTag(.comptime_int), abi_size);
4099}4935}
41004936
4101fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {4937fn zirBitSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
4102 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4938 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4103 const src = inst_data.src();4939 const src = inst_data.src();
4940 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
4941 const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
4942 const target = sema.mod.getTarget();
4943 const bit_size = operand_ty.bitSize(target);
4944 return sema.mod.constIntUnsigned(sema.arena, src, Type.initTag(.comptime_int), bit_size);
4945}
4946
4947fn zirThis(
4948 sema: *Sema,
4949 block: *Scope.Block,
4950 extended: Zir.Inst.Extended.InstData,
4951) InnerError!*Inst {
4952 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
4953 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirThis", .{});
4954}
4955
4956fn zirRetAddr(
4957 sema: *Sema,
4958 block: *Scope.Block,
4959 extended: Zir.Inst.Extended.InstData,
4960) InnerError!*Inst {
4961 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
4962 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirRetAddr", .{});
4963}
4964
4965fn zirBuiltinSrc(
4966 sema: *Sema,
4967 block: *Scope.Block,
4968 extended: Zir.Inst.Extended.InstData,
4969) InnerError!*Inst {
4970 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
4971 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirBuiltinSrc", .{});
4972}
4973
4974fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
4975 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4976 const src = inst_data.src();
4977 const ty = try sema.resolveType(block, src, inst_data.operand);
4978 const type_info_ty = try sema.getBuiltinType(block, src, "TypeInfo");
4979 const target = sema.mod.getTarget();
4980
4981 switch (ty.zigTypeTag()) {
4982 .Fn => {
4983 const field_values = try sema.arena.alloc(Value, 6);
4984 // calling_convention: CallingConvention,
4985 field_values[0] = try Value.Tag.enum_field_index.create(
4986 sema.arena,
4987 @enumToInt(ty.fnCallingConvention()),
4988 );
4989 // alignment: comptime_int,
4990 field_values[1] = try Value.Tag.int_u64.create(sema.arena, ty.abiAlignment(target));
4991 // is_generic: bool,
4992 field_values[2] = Value.initTag(.bool_false); // TODO
4993 // is_var_args: bool,
4994 field_values[3] = Value.initTag(.bool_false); // TODO
4995 // return_type: ?type,
4996 field_values[4] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());
4997 // args: []const FnArg,
4998 field_values[5] = Value.initTag(.null_value); // TODO
4999
5000 return sema.mod.constInst(sema.arena, src, .{
5001 .ty = type_info_ty,
5002 .val = try Value.Tag.@"union".create(sema.arena, .{
5003 .tag = try Value.Tag.enum_field_index.create(
5004 sema.arena,
5005 @enumToInt(@typeInfo(std.builtin.TypeInfo).Union.tag_type.?.Fn),
5006 ),
5007 .val = try Value.Tag.@"struct".create(sema.arena, field_values.ptr),
5008 }),
5009 });
5010 },
5011 else => |t| return sema.mod.fail(&block.base, src, "TODO: implement zirTypeInfo for {s}", .{
5012 @tagName(t),
5013 }),
5014 }
5015}
5016
5017fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5018 const zir_datas = sema.code.instructions.items(.data);
5019 const inst_data = zir_datas[inst].un_node;
5020 const src = inst_data.src();
4104 const operand = try sema.resolveInst(inst_data.operand);5021 const operand = try sema.resolveInst(inst_data.operand);
4105 return sema.mod.constType(sema.arena, src, operand.ty);5022 return sema.mod.constType(sema.arena, src, operand.ty);
4106}5023}
41075024
4108fn zirTypeofElem(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {5025fn zirTypeofElem(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
4109 const inst_data = sema.code.instructions.items(.data)[inst].un_node;5026 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4110 const src = inst_data.src();5027 const src = inst_data.src();
4111 const operand_ptr = try sema.resolveInst(inst_data.operand);5028 const operand_ptr = try sema.resolveInst(inst_data.operand);
...@@ -4113,16 +5030,31 @@ fn zirTypeofElem(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr...@@ -4113,16 +5030,31 @@ fn zirTypeofElem(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
4113 return sema.mod.constType(sema.arena, src, elem_ty);5030 return sema.mod.constType(sema.arena, src, elem_ty);
4114}5031}
41155032
4116fn zirTypeofPeer(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {5033fn zirTypeofLog2IntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5034 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5035 const src = inst_data.src();
5036 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirTypeofLog2IntType", .{});
5037}
5038
5039fn zirLog2IntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5040 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5041 const src = inst_data.src();
5042 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirLog2IntType", .{});
5043}
5044
5045fn zirTypeofPeer(
5046 sema: *Sema,
5047 block: *Scope.Block,
5048 extended: Zir.Inst.Extended.InstData,
5049) InnerError!*Inst {
4117 const tracy = trace(@src());5050 const tracy = trace(@src());
4118 defer tracy.end();5051 defer tracy.end();
41195052
4120 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;5053 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
4121 const src = inst_data.src();5054 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
4122 const extra = sema.code.extraData(zir.Inst.MultiOp, inst_data.payload_index);5055 const args = sema.code.refSlice(extra.end, extended.small);
4123 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
41245056
4125 const inst_list = try sema.gpa.alloc(*ir.Inst, extra.data.operands_len);5057 const inst_list = try sema.gpa.alloc(*ir.Inst, args.len);
4126 defer sema.gpa.free(inst_list);5058 defer sema.gpa.free(inst_list);
41275059
4128 for (args) |arg_ref, i| {5060 for (args) |arg_ref, i| {
...@@ -4133,7 +5065,7 @@ fn zirTypeofPeer(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr...@@ -4133,7 +5065,7 @@ fn zirTypeofPeer(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
4133 return sema.mod.constType(sema.arena, src, result_type);5065 return sema.mod.constType(sema.arena, src, result_type);
4134}5066}
41355067
4136fn zirBoolNot(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {5068fn zirBoolNot(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
4137 const tracy = trace(@src());5069 const tracy = trace(@src());
4138 defer tracy.end();5070 defer tracy.end();
41395071
...@@ -4153,7 +5085,7 @@ fn zirBoolNot(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -4153,7 +5085,7 @@ fn zirBoolNot(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
4153fn zirBoolOp(5085fn zirBoolOp(
4154 sema: *Sema,5086 sema: *Sema,
4155 block: *Scope.Block,5087 block: *Scope.Block,
4156 inst: zir.Inst.Index,5088 inst: Zir.Inst.Index,
4157 comptime is_bool_or: bool,5089 comptime is_bool_or: bool,
4158) InnerError!*Inst {5090) InnerError!*Inst {
4159 const tracy = trace(@src());5091 const tracy = trace(@src());
...@@ -4184,7 +5116,7 @@ fn zirBoolOp(...@@ -4184,7 +5116,7 @@ fn zirBoolOp(
4184fn zirBoolBr(5116fn zirBoolBr(
4185 sema: *Sema,5117 sema: *Sema,
4186 parent_block: *Scope.Block,5118 parent_block: *Scope.Block,
4187 inst: zir.Inst.Index,5119 inst: Zir.Inst.Index,
4188 is_bool_or: bool,5120 is_bool_or: bool,
4189) InnerError!*Inst {5121) InnerError!*Inst {
4190 const tracy = trace(@src());5122 const tracy = trace(@src());
...@@ -4194,7 +5126,7 @@ fn zirBoolBr(...@@ -4194,7 +5126,7 @@ fn zirBoolBr(
4194 const inst_data = datas[inst].bool_br;5126 const inst_data = datas[inst].bool_br;
4195 const src: LazySrcLoc = .unneeded;5127 const src: LazySrcLoc = .unneeded;
4196 const lhs = try sema.resolveInst(inst_data.lhs);5128 const lhs = try sema.resolveInst(inst_data.lhs);
4197 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);5129 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
4198 const body = sema.code.extra[extra.end..][0..extra.data.body_len];5130 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
41995131
4200 if (try sema.resolveDefinedValue(parent_block, src, lhs)) |lhs_val| {5132 if (try sema.resolveDefinedValue(parent_block, src, lhs)) |lhs_val| {
...@@ -4238,9 +5170,9 @@ fn zirBoolBr(...@@ -4238,9 +5170,9 @@ fn zirBoolBr(
4238 const rhs_result = try sema.resolveBody(rhs_block, body);5170 const rhs_result = try sema.resolveBody(rhs_block, body);
4239 _ = try rhs_block.addBr(src, block_inst, rhs_result);5171 _ = try rhs_block.addBr(src, block_inst, rhs_result);
42405172
4241 const tzir_then_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, then_block.instructions.items) };5173 const air_then_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, then_block.instructions.items) };
4242 const tzir_else_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, else_block.instructions.items) };5174 const air_else_body: ir.Body = .{ .instructions = try sema.arena.dupe(*Inst, else_block.instructions.items) };
4243 _ = try child_block.addCondBr(src, lhs, tzir_then_body, tzir_else_body);5175 _ = try child_block.addCondBr(src, lhs, air_then_body, air_else_body);
42445176
4245 block_inst.body = .{5177 block_inst.body = .{
4246 .instructions = try sema.arena.dupe(*Inst, child_block.instructions.items),5178 .instructions = try sema.arena.dupe(*Inst, child_block.instructions.items),
...@@ -4252,7 +5184,7 @@ fn zirBoolBr(...@@ -4252,7 +5184,7 @@ fn zirBoolBr(
4252fn zirIsNull(5184fn zirIsNull(
4253 sema: *Sema,5185 sema: *Sema,
4254 block: *Scope.Block,5186 block: *Scope.Block,
4255 inst: zir.Inst.Index,5187 inst: Zir.Inst.Index,
4256 invert_logic: bool,5188 invert_logic: bool,
4257) InnerError!*Inst {5189) InnerError!*Inst {
4258 const tracy = trace(@src());5190 const tracy = trace(@src());
...@@ -4267,7 +5199,7 @@ fn zirIsNull(...@@ -4267,7 +5199,7 @@ fn zirIsNull(
4267fn zirIsNullPtr(5199fn zirIsNullPtr(
4268 sema: *Sema,5200 sema: *Sema,
4269 block: *Scope.Block,5201 block: *Scope.Block,
4270 inst: zir.Inst.Index,5202 inst: Zir.Inst.Index,
4271 invert_logic: bool,5203 invert_logic: bool,
4272) InnerError!*Inst {5204) InnerError!*Inst {
4273 const tracy = trace(@src());5205 const tracy = trace(@src());
...@@ -4280,7 +5212,7 @@ fn zirIsNullPtr(...@@ -4280,7 +5212,7 @@ fn zirIsNullPtr(
4280 return sema.analyzeIsNull(block, src, loaded, invert_logic);5212 return sema.analyzeIsNull(block, src, loaded, invert_logic);
4281}5213}
42825214
4283fn zirIsErr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {5215fn zirIsErr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
4284 const tracy = trace(@src());5216 const tracy = trace(@src());
4285 defer tracy.end();5217 defer tracy.end();
42865218
...@@ -4289,7 +5221,7 @@ fn zirIsErr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*...@@ -4289,7 +5221,7 @@ fn zirIsErr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*
4289 return sema.analyzeIsErr(block, inst_data.src(), operand);5221 return sema.analyzeIsErr(block, inst_data.src(), operand);
4290}5222}
42915223
4292fn zirIsErrPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {5224fn zirIsErrPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
4293 const tracy = trace(@src());5225 const tracy = trace(@src());
4294 defer tracy.end();5226 defer tracy.end();
42955227
...@@ -4303,15 +5235,15 @@ fn zirIsErrPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro...@@ -4303,15 +5235,15 @@ fn zirIsErrPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
4303fn zirCondbr(5235fn zirCondbr(
4304 sema: *Sema,5236 sema: *Sema,
4305 parent_block: *Scope.Block,5237 parent_block: *Scope.Block,
4306 inst: zir.Inst.Index,5238 inst: Zir.Inst.Index,
4307) InnerError!zir.Inst.Index {5239) InnerError!Zir.Inst.Index {
4308 const tracy = trace(@src());5240 const tracy = trace(@src());
4309 defer tracy.end();5241 defer tracy.end();
43105242
4311 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;5243 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
4312 const src = inst_data.src();5244 const src = inst_data.src();
4313 const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node };5245 const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node };
4314 const extra = sema.code.extraData(zir.Inst.CondBr, inst_data.payload_index);5246 const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
43155247
4316 const then_body = sema.code.extra[extra.end..][0..extra.data.then_body_len];5248 const then_body = sema.code.extra[extra.end..][0..extra.data.then_body_len];
4317 const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];5249 const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
...@@ -4329,22 +5261,22 @@ fn zirCondbr(...@@ -4329,22 +5261,22 @@ fn zirCondbr(
4329 defer sub_block.instructions.deinit(sema.gpa);5261 defer sub_block.instructions.deinit(sema.gpa);
43305262
4331 _ = try sema.analyzeBody(&sub_block, then_body);5263 _ = try sema.analyzeBody(&sub_block, then_body);
4332 const tzir_then_body: ir.Body = .{5264 const air_then_body: ir.Body = .{
4333 .instructions = try sema.arena.dupe(*Inst, sub_block.instructions.items),5265 .instructions = try sema.arena.dupe(*Inst, sub_block.instructions.items),
4334 };5266 };
43355267
4336 sub_block.instructions.shrinkRetainingCapacity(0);5268 sub_block.instructions.shrinkRetainingCapacity(0);
43375269
4338 _ = try sema.analyzeBody(&sub_block, else_body);5270 _ = try sema.analyzeBody(&sub_block, else_body);
4339 const tzir_else_body: ir.Body = .{5271 const air_else_body: ir.Body = .{
4340 .instructions = try sema.arena.dupe(*Inst, sub_block.instructions.items),5272 .instructions = try sema.arena.dupe(*Inst, sub_block.instructions.items),
4341 };5273 };
43425274
4343 _ = try parent_block.addCondBr(src, cond, tzir_then_body, tzir_else_body);5275 _ = try parent_block.addCondBr(src, cond, air_then_body, air_else_body);
4344 return always_noreturn;5276 return always_noreturn;
4345}5277}
43465278
4347fn zirUnreachable(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {5279fn zirUnreachable(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Zir.Inst.Index {
4348 const tracy = trace(@src());5280 const tracy = trace(@src());
4349 defer tracy.end();5281 defer tracy.end();
43505282
...@@ -4364,9 +5296,9 @@ fn zirUnreachable(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE...@@ -4364,9 +5296,9 @@ fn zirUnreachable(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE
4364fn zirRetTok(5296fn zirRetTok(
4365 sema: *Sema,5297 sema: *Sema,
4366 block: *Scope.Block,5298 block: *Scope.Block,
4367 inst: zir.Inst.Index,5299 inst: Zir.Inst.Index,
4368 need_coercion: bool,5300 need_coercion: bool,
4369) InnerError!zir.Inst.Index {5301) InnerError!Zir.Inst.Index {
4370 const tracy = trace(@src());5302 const tracy = trace(@src());
4371 defer tracy.end();5303 defer tracy.end();
43725304
...@@ -4377,7 +5309,7 @@ fn zirRetTok(...@@ -4377,7 +5309,7 @@ fn zirRetTok(
4377 return sema.analyzeRet(block, operand, src, need_coercion);5309 return sema.analyzeRet(block, operand, src, need_coercion);
4378}5310}
43795311
4380fn zirRetNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {5312fn zirRetNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Zir.Inst.Index {
4381 const tracy = trace(@src());5313 const tracy = trace(@src());
4382 defer tracy.end();5314 defer tracy.end();
43835315
...@@ -4394,7 +5326,7 @@ fn analyzeRet(...@@ -4394,7 +5326,7 @@ fn analyzeRet(
4394 operand: *Inst,5326 operand: *Inst,
4395 src: LazySrcLoc,5327 src: LazySrcLoc,
4396 need_coercion: bool,5328 need_coercion: bool,
4397) InnerError!zir.Inst.Index {5329) InnerError!Zir.Inst.Index {
4398 if (block.inlining) |inlining| {5330 if (block.inlining) |inlining| {
4399 // We are inlining a function call; rewrite the `ret` as a `break`.5331 // We are inlining a function call; rewrite the `ret` as a `break`.
4400 try inlining.merges.results.append(sema.gpa, operand);5332 try inlining.merges.results.append(sema.gpa, operand);
...@@ -4404,7 +5336,7 @@ fn analyzeRet(...@@ -4404,7 +5336,7 @@ fn analyzeRet(
44045336
4405 if (need_coercion) {5337 if (need_coercion) {
4406 if (sema.func) |func| {5338 if (sema.func) |func| {
4407 const fn_ty = func.owner_decl.typed_value.most_recent.typed_value.ty;5339 const fn_ty = func.owner_decl.ty;
4408 const fn_ret_ty = fn_ty.fnReturnType();5340 const fn_ret_ty = fn_ty.fnReturnType();
4409 const casted_operand = try sema.coerce(block, fn_ret_ty, operand, src);5341 const casted_operand = try sema.coerce(block, fn_ret_ty, operand, src);
4410 if (fn_ret_ty.zigTypeTag() == .Void)5342 if (fn_ret_ty.zigTypeTag() == .Void)
...@@ -4418,113 +5350,762 @@ fn analyzeRet(...@@ -4418,113 +5350,762 @@ fn analyzeRet(
4418 return always_noreturn;5350 return always_noreturn;
4419}5351}
44205352
4421fn floatOpAllowed(tag: zir.Inst.Tag) bool {5353fn floatOpAllowed(tag: Zir.Inst.Tag) bool {
4422 // extend this swich as additional operators are implemented5354 // extend this swich as additional operators are implemented
4423 return switch (tag) {5355 return switch (tag) {
4424 .add, .sub => true,5356 .add, .sub => true,
4425 else => false,5357 else => false,
4426 };5358 };
4427}5359}
5360
5361fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5362 const tracy = trace(@src());
5363 defer tracy.end();
5364
5365 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type_simple;
5366 const elem_type = try sema.resolveType(block, .unneeded, inst_data.elem_type);
5367 const ty = try sema.mod.ptrType(
5368 sema.arena,
5369 elem_type,
5370 null,
5371 0,
5372 0,
5373 0,
5374 inst_data.is_mutable,
5375 inst_data.is_allowzero,
5376 inst_data.is_volatile,
5377 inst_data.size,
5378 );
5379 return sema.mod.constType(sema.arena, .unneeded, ty);
5380}
5381
5382fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5383 const tracy = trace(@src());
5384 defer tracy.end();
5385
5386 const src: LazySrcLoc = .unneeded;
5387 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type;
5388 const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index);
5389
5390 var extra_i = extra.end;
5391
5392 const sentinel = if (inst_data.flags.has_sentinel) blk: {
5393 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
5394 extra_i += 1;
5395 break :blk (try sema.resolveInstConst(block, .unneeded, ref)).val;
5396 } else null;
5397
5398 const abi_align = if (inst_data.flags.has_align) blk: {
5399 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
5400 extra_i += 1;
5401 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u32);
5402 } else 0;
5403
5404 const bit_start = if (inst_data.flags.has_bit_range) blk: {
5405 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
5406 extra_i += 1;
5407 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16);
5408 } else 0;
5409
5410 const bit_end = if (inst_data.flags.has_bit_range) blk: {
5411 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
5412 extra_i += 1;
5413 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16);
5414 } else 0;
5415
5416 if (bit_end != 0 and bit_start >= bit_end * 8)
5417 return sema.mod.fail(&block.base, src, "bit offset starts after end of host integer", .{});
5418
5419 const elem_type = try sema.resolveType(block, .unneeded, extra.data.elem_type);
5420
5421 const ty = try sema.mod.ptrType(
5422 sema.arena,
5423 elem_type,
5424 sentinel,
5425 abi_align,
5426 bit_start,
5427 bit_end,
5428 inst_data.flags.is_mutable,
5429 inst_data.flags.is_allowzero,
5430 inst_data.flags.is_volatile,
5431 inst_data.size,
5432 );
5433 return sema.mod.constType(sema.arena, src, ty);
5434}
5435
5436fn zirStructInitEmpty(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5437 const tracy = trace(@src());
5438 defer tracy.end();
5439
5440 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5441 const src = inst_data.src();
5442 const struct_type = try sema.resolveType(block, src, inst_data.operand);
5443
5444 return sema.mod.constInst(sema.arena, src, .{
5445 .ty = struct_type,
5446 .val = Value.initTag(.empty_struct_value),
5447 });
5448}
5449
5450fn zirUnionInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5451 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5452 const src = inst_data.src();
5453 return sema.mod.fail(&block.base, src, "TODO: Sema.zirUnionInitPtr", .{});
5454}
5455
5456fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst {
5457 const mod = sema.mod;
5458 const gpa = sema.gpa;
5459 const zir_datas = sema.code.instructions.items(.data);
5460 const inst_data = zir_datas[inst].pl_node;
5461 const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);
5462 const src = inst_data.src();
5463
5464 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;
5465 const first_field_type_data = zir_datas[first_item.field_type].pl_node;
5466 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;
5467 const unresolved_struct_type = try sema.resolveType(block, src, first_field_type_extra.container_type);
5468 const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_type);
5469 const struct_obj = struct_ty.castTag(.@"struct").?.data;
5470
5471 // Maps field index to field_type index of where it was already initialized.
5472 // For making sure all fields are accounted for and no fields are duplicated.
5473 const found_fields = try gpa.alloc(Zir.Inst.Index, struct_obj.fields.entries.items.len);
5474 defer gpa.free(found_fields);
5475 mem.set(Zir.Inst.Index, found_fields, 0);
5476
5477 // The init values to use for the struct instance.
5478 const field_inits = try gpa.alloc(*ir.Inst, struct_obj.fields.entries.items.len);
5479 defer gpa.free(field_inits);
5480
5481 var field_i: u32 = 0;
5482 var extra_index = extra.end;
5483
5484 while (field_i < extra.data.fields_len) : (field_i += 1) {
5485 const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index);
5486 extra_index = item.end;
5487
5488 const field_type_data = zir_datas[item.data.field_type].pl_node;
5489 const field_src: LazySrcLoc = .{ .node_offset_back2tok = field_type_data.src_node };
5490 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
5491 const field_name = sema.code.nullTerminatedString(field_type_extra.name_start);
5492 const field_index = struct_obj.fields.getIndex(field_name) orelse
5493 return sema.failWithBadFieldAccess(block, struct_obj, field_src, field_name);
5494 if (found_fields[field_index] != 0) {
5495 const other_field_type = found_fields[field_index];
5496 const other_field_type_data = zir_datas[other_field_type].pl_node;
5497 const other_field_src: LazySrcLoc = .{ .node_offset_back2tok = other_field_type_data.src_node };
5498 const msg = msg: {
5499 const msg = try mod.errMsg(&block.base, field_src, "duplicate field", .{});
5500 errdefer msg.destroy(gpa);
5501 try mod.errNote(&block.base, other_field_src, msg, "other field here", .{});
5502 break :msg msg;
5503 };
5504 return mod.failWithOwnedErrorMsg(&block.base, msg);
5505 }
5506 found_fields[field_index] = item.data.field_type;
5507 field_inits[field_index] = try sema.resolveInst(item.data.init);
5508 }
5509
5510 var root_msg: ?*Module.ErrorMsg = null;
5511
5512 for (found_fields) |field_type_inst, i| {
5513 if (field_type_inst != 0) continue;
5514
5515 // Check if the field has a default init.
5516 const field = struct_obj.fields.entries.items[i].value;
5517 if (field.default_val.tag() == .unreachable_value) {
5518 const field_name = struct_obj.fields.entries.items[i].key;
5519 const template = "missing struct field: {s}";
5520 const args = .{field_name};
5521 if (root_msg) |msg| {
5522 try mod.errNote(&block.base, src, msg, template, args);
5523 } else {
5524 root_msg = try mod.errMsg(&block.base, src, template, args);
5525 }
5526 } else {
5527 field_inits[i] = try mod.constInst(sema.arena, src, .{
5528 .ty = field.ty,
5529 .val = field.default_val,
5530 });
5531 }
5532 }
5533 if (root_msg) |msg| {
5534 const fqn = try struct_obj.getFullyQualifiedName(gpa);
5535 defer gpa.free(fqn);
5536 try mod.errNoteNonLazy(
5537 struct_obj.srcLoc(),
5538 msg,
5539 "struct '{s}' declared here",
5540 .{fqn},
5541 );
5542 return mod.failWithOwnedErrorMsg(&block.base, msg);
5543 }
5544
5545 const is_comptime = for (field_inits) |field_init| {
5546 if (field_init.value() == null) {
5547 break false;
5548 }
5549 } else true;
5550
5551 if (is_comptime) {
5552 const values = try sema.arena.alloc(Value, field_inits.len);
5553 for (field_inits) |field_init, i| {
5554 values[i] = field_init.value().?;
5555 }
5556 return mod.constInst(sema.arena, src, .{
5557 .ty = struct_ty,
5558 .val = try Value.Tag.@"struct".create(sema.arena, values.ptr),
5559 });
5560 }
5561
5562 return mod.fail(&block.base, src, "TODO: Sema.zirStructInit for runtime-known struct values", .{});
5563}
5564
5565fn zirStructInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst {
5566 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5567 const src = inst_data.src();
5568 return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInitAnon", .{});
5569}
5570
5571fn zirArrayInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst {
5572 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5573 const src = inst_data.src();
5574 return sema.mod.fail(&block.base, src, "TODO: Sema.zirArrayInit", .{});
5575}
5576
5577fn zirArrayInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst {
5578 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5579 const src = inst_data.src();
5580 return sema.mod.fail(&block.base, src, "TODO: Sema.zirArrayInitAnon", .{});
5581}
5582
5583fn zirFieldTypeRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5584 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5585 const src = inst_data.src();
5586 return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldTypeRef", .{});
5587}
5588
5589fn zirFieldType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5590 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5591 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
5592 const src = inst_data.src();
5593 const field_name = sema.code.nullTerminatedString(extra.name_start);
5594 const unresolved_struct_type = try sema.resolveType(block, src, extra.container_type);
5595 if (unresolved_struct_type.zigTypeTag() != .Struct) {
5596 return sema.mod.fail(&block.base, src, "expected struct; found '{}'", .{
5597 unresolved_struct_type,
5598 });
5599 }
5600 const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_type);
5601 const struct_obj = struct_ty.castTag(.@"struct").?.data;
5602 const field = struct_obj.fields.get(field_name) orelse
5603 return sema.failWithBadFieldAccess(block, struct_obj, src, field_name);
5604 return sema.mod.constType(sema.arena, src, field.ty);
5605}
5606
5607fn zirErrorReturnTrace(
5608 sema: *Sema,
5609 block: *Scope.Block,
5610 extended: Zir.Inst.Extended.InstData,
5611) InnerError!*Inst {
5612 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
5613 return sema.mod.fail(&block.base, src, "TODO: Sema.zirErrorReturnTrace", .{});
5614}
5615
5616fn zirFrame(
5617 sema: *Sema,
5618 block: *Scope.Block,
5619 extended: Zir.Inst.Extended.InstData,
5620) InnerError!*Inst {
5621 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
5622 return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrame", .{});
5623}
5624
5625fn zirFrameAddress(
5626 sema: *Sema,
5627 block: *Scope.Block,
5628 extended: Zir.Inst.Extended.InstData,
5629) InnerError!*Inst {
5630 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
5631 return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrameAddress", .{});
5632}
5633
5634fn zirAlignOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5635 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5636 const src = inst_data.src();
5637 return sema.mod.fail(&block.base, src, "TODO: Sema.zirAlignOf", .{});
5638}
5639
5640fn zirBoolToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5641 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5642 const src = inst_data.src();
5643 return sema.mod.fail(&block.base, src, "TODO: Sema.zirBoolToInt", .{});
5644}
5645
5646fn zirEmbedFile(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5647 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5648 const src = inst_data.src();
5649 return sema.mod.fail(&block.base, src, "TODO: Sema.zirEmbedFile", .{});
5650}
5651
5652fn zirErrorName(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5653 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5654 const src = inst_data.src();
5655 return sema.mod.fail(&block.base, src, "TODO: Sema.zirErrorName", .{});
5656}
5657
5658fn zirUnaryMath(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5659 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5660 const src = inst_data.src();
5661 return sema.mod.fail(&block.base, src, "TODO: Sema.zirUnaryMath", .{});
5662}
5663
5664fn zirTagName(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5665 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5666 const src = inst_data.src();
5667 return sema.mod.fail(&block.base, src, "TODO: Sema.zirTagName", .{});
5668}
5669
5670fn zirReify(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5671 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5672 const src = inst_data.src();
5673 return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify", .{});
5674}
5675
5676fn zirTypeName(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5677 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5678 const src = inst_data.src();
5679 return sema.mod.fail(&block.base, src, "TODO: Sema.zirTypeName", .{});
5680}
5681
5682fn zirFrameType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5683 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5684 const src = inst_data.src();
5685 return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrameType", .{});
5686}
5687
5688fn zirFrameSize(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5689 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5690 const src = inst_data.src();
5691 return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrameSize", .{});
5692}
5693
5694fn zirFloatToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5695 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5696 const src = inst_data.src();
5697 return sema.mod.fail(&block.base, src, "TODO: Sema.zirFloatToInt", .{});
5698}
5699
5700fn zirIntToFloat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5701 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5702 const src = inst_data.src();
5703 return sema.mod.fail(&block.base, src, "TODO: Sema.zirIntToFloat", .{});
5704}
5705
5706fn zirIntToPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5707 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5708 const src = inst_data.src();
5709 return sema.mod.fail(&block.base, src, "TODO: Sema.zirIntToPtr", .{});
5710}
5711
5712fn zirErrSetCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5713 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5714 const src = inst_data.src();
5715 return sema.mod.fail(&block.base, src, "TODO: Sema.zirErrSetCast", .{});
5716}
5717
5718fn zirPtrCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5719 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5720 const src = inst_data.src();
5721 return sema.mod.fail(&block.base, src, "TODO: Sema.zirPtrCast", .{});
5722}
5723
5724fn zirTruncate(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5725 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5726 const src = inst_data.src();
5727 return sema.mod.fail(&block.base, src, "TODO: Sema.zirTruncate", .{});
5728}
5729
5730fn zirAlignCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5731 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5732 const src = inst_data.src();
5733 return sema.mod.fail(&block.base, src, "TODO: Sema.zirAlignCast", .{});
5734}
5735
5736fn zirClz(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5737 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5738 const src = inst_data.src();
5739 return sema.mod.fail(&block.base, src, "TODO: Sema.zirClz", .{});
5740}
5741
5742fn zirCtz(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5743 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5744 const src = inst_data.src();
5745 return sema.mod.fail(&block.base, src, "TODO: Sema.zirCtz", .{});
5746}
5747
5748fn zirPopCount(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5749 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5750 const src = inst_data.src();
5751 return sema.mod.fail(&block.base, src, "TODO: Sema.zirPopCount", .{});
5752}
5753
5754fn zirByteSwap(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5755 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5756 const src = inst_data.src();
5757 return sema.mod.fail(&block.base, src, "TODO: Sema.zirByteSwap", .{});
5758}
5759
5760fn zirBitReverse(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5761 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5762 const src = inst_data.src();
5763 return sema.mod.fail(&block.base, src, "TODO: Sema.zirBitReverse", .{});
5764}
5765
5766fn zirDivExact(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5767 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5768 const src = inst_data.src();
5769 return sema.mod.fail(&block.base, src, "TODO: Sema.zirDivExact", .{});
5770}
5771
5772fn zirDivFloor(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5773 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5774 const src = inst_data.src();
5775 return sema.mod.fail(&block.base, src, "TODO: Sema.zirDivFloor", .{});
5776}
5777
5778fn zirDivTrunc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5779 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5780 const src = inst_data.src();
5781 return sema.mod.fail(&block.base, src, "TODO: Sema.zirDivTrunc", .{});
5782}
5783
5784fn zirMod(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5785 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5786 const src = inst_data.src();
5787 return sema.mod.fail(&block.base, src, "TODO: Sema.zirMod", .{});
5788}
5789
5790fn zirRem(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5791 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5792 const src = inst_data.src();
5793 return sema.mod.fail(&block.base, src, "TODO: Sema.zirRem", .{});
5794}
5795
5796fn zirShlExact(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5797 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5798 const src = inst_data.src();
5799 return sema.mod.fail(&block.base, src, "TODO: Sema.zirShlExact", .{});
5800}
5801
5802fn zirShrExact(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5803 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5804 const src = inst_data.src();
5805 return sema.mod.fail(&block.base, src, "TODO: Sema.zirShrExact", .{});
5806}
5807
5808fn zirBitOffsetOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5809 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5810 const src = inst_data.src();
5811 return sema.mod.fail(&block.base, src, "TODO: Sema.zirBitOffsetOf", .{});
5812}
5813
5814fn zirByteOffsetOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5815 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5816 const src = inst_data.src();
5817 return sema.mod.fail(&block.base, src, "TODO: Sema.zirByteOffsetOf", .{});
5818}
5819
5820fn zirCmpxchg(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5821 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5822 const src = inst_data.src();
5823 return sema.mod.fail(&block.base, src, "TODO: Sema.zirCmpxchg", .{});
5824}
5825
5826fn zirSplat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5827 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5828 const src = inst_data.src();
5829 return sema.mod.fail(&block.base, src, "TODO: Sema.zirSplat", .{});
5830}
5831
5832fn zirReduce(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5833 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5834 const src = inst_data.src();
5835 return sema.mod.fail(&block.base, src, "TODO: Sema.zirReduce", .{});
5836}
5837
5838fn zirShuffle(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5839 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5840 const src = inst_data.src();
5841 return sema.mod.fail(&block.base, src, "TODO: Sema.zirShuffle", .{});
5842}
5843
5844fn zirAtomicLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5845 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5846 const src = inst_data.src();
5847 return sema.mod.fail(&block.base, src, "TODO: Sema.zirAtomicLoad", .{});
5848}
5849
5850fn zirAtomicRmw(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5851 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5852 const src = inst_data.src();
5853 return sema.mod.fail(&block.base, src, "TODO: Sema.zirAtomicRmw", .{});
5854}
5855
5856fn zirAtomicStore(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5857 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5858 const src = inst_data.src();
5859 return sema.mod.fail(&block.base, src, "TODO: Sema.zirAtomicStore", .{});
5860}
5861
5862fn zirMulAdd(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5863 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5864 const src = inst_data.src();
5865 return sema.mod.fail(&block.base, src, "TODO: Sema.zirMulAdd", .{});
5866}
5867
5868fn zirBuiltinCall(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5869 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5870 const src = inst_data.src();
5871 return sema.mod.fail(&block.base, src, "TODO: Sema.zirBuiltinCall", .{});
5872}
5873
5874fn zirFieldPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5875 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5876 const src = inst_data.src();
5877 return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldPtrType", .{});
5878}
5879
5880fn zirFieldParentPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5881 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5882 const src = inst_data.src();
5883 return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldParentPtr", .{});
5884}
5885
5886fn zirMemcpy(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5887 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5888 const src = inst_data.src();
5889 return sema.mod.fail(&block.base, src, "TODO: Sema.zirMemcpy", .{});
5890}
5891
5892fn zirMemset(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5893 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5894 const src = inst_data.src();
5895 return sema.mod.fail(&block.base, src, "TODO: Sema.zirMemset", .{});
5896}
5897
5898fn zirBuiltinAsyncCall(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5899 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5900 const src = inst_data.src();
5901 return sema.mod.fail(&block.base, src, "TODO: Sema.zirBuiltinAsyncCall", .{});
5902}
5903
5904fn zirResume(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
5905 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5906 const src = inst_data.src();
5907 return sema.mod.fail(&block.base, src, "TODO: Sema.zirResume", .{});
5908}
5909
5910fn zirAwait(
5911 sema: *Sema,
5912 block: *Scope.Block,
5913 inst: Zir.Inst.Index,
5914 is_nosuspend: bool,
5915) InnerError!*Inst {
5916 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5917 const src = inst_data.src();
5918 return sema.mod.fail(&block.base, src, "TODO: Sema.zirAwait", .{});
5919}
5920
5921fn zirVarExtended(
5922 sema: *Sema,
5923 block: *Scope.Block,
5924 extended: Zir.Inst.Extended.InstData,
5925) InnerError!*Inst {
5926 const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);
5927 const src = sema.src;
5928 const align_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at align
5929 const ty_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at type
5930 const mut_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at mut token
5931 const init_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at init expr
5932 const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small);
5933 const var_ty = try sema.resolveType(block, ty_src, extra.data.var_type);
5934
5935 var extra_index: usize = extra.end;
5936
5937 const lib_name: ?[]const u8 = if (small.has_lib_name) blk: {
5938 const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
5939 extra_index += 1;
5940 break :blk lib_name;
5941 } else null;
5942
5943 // ZIR supports encoding this information but it is not used; the information
5944 // is encoded via the Decl entry.
5945 assert(!small.has_align);
5946 //const align_val: Value = if (small.has_align) blk: {
5947 // const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
5948 // extra_index += 1;
5949 // const align_tv = try sema.resolveInstConst(block, align_src, align_ref);
5950 // break :blk align_tv.val;
5951 //} else Value.initTag(.null_value);
5952
5953 const init_val: Value = if (small.has_init) blk: {
5954 const init_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
5955 extra_index += 1;
5956 const init_tv = try sema.resolveInstConst(block, init_src, init_ref);
5957 break :blk init_tv.val;
5958 } else Value.initTag(.unreachable_value);
44285959
4429fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {5960 if (!var_ty.isValidVarType(small.is_extern)) {
4430 const tracy = trace(@src());5961 return sema.mod.fail(&block.base, mut_src, "variable of type '{}' must be const", .{
4431 defer tracy.end();5962 var_ty,
5963 });
5964 }
44325965
4433 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type_simple;5966 if (lib_name != null) {
4434 const elem_type = try sema.resolveType(block, .unneeded, inst_data.elem_type);5967 // Look at the sema code for functions which has this logic, it just needs to
4435 const ty = try sema.mod.ptrType(5968 // be extracted and shared by both var and func
4436 sema.arena,5969 return sema.mod.fail(&block.base, src, "TODO: handle var with lib_name in Sema", .{});
4437 elem_type,5970 }
4438 null,5971
4439 0,5972 const new_var = try sema.gpa.create(Module.Var);
4440 0,5973 new_var.* = .{
4441 0,5974 .owner_decl = sema.owner_decl,
4442 inst_data.is_mutable,5975 .init = init_val,
4443 inst_data.is_allowzero,5976 .is_extern = small.is_extern,
4444 inst_data.is_volatile,5977 .is_mutable = true, // TODO get rid of this unused field
4445 inst_data.size,5978 .is_threadlocal = small.is_threadlocal,
4446 );5979 };
4447 return sema.mod.constType(sema.arena, .unneeded, ty);5980 const result = try sema.mod.constInst(sema.arena, src, .{
5981 .ty = var_ty,
5982 .val = try Value.Tag.variable.create(sema.arena, new_var),
5983 });
5984 return result;
4448}5985}
44495986
4450fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {5987fn zirFuncExtended(
5988 sema: *Sema,
5989 block: *Scope.Block,
5990 extended: Zir.Inst.Extended.InstData,
5991 inst: Zir.Inst.Index,
5992) InnerError!*Inst {
4451 const tracy = trace(@src());5993 const tracy = trace(@src());
4452 defer tracy.end();5994 defer tracy.end();
44535995
4454 const src: LazySrcLoc = .unneeded;5996 const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, extended.operand);
4455 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type;5997 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
4456 const extra = sema.code.extraData(zir.Inst.PtrType, inst_data.payload_index);5998 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = extra.data.src_node };
5999 const align_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at align
6000 const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
44576001
4458 var extra_i = extra.end;6002 var extra_index: usize = extra.end;
44596003
4460 const sentinel = if (inst_data.flags.has_sentinel) blk: {6004 const lib_name: ?[]const u8 = if (small.has_lib_name) blk: {
4461 const ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_i]);6005 const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
4462 extra_i += 1;6006 extra_index += 1;
4463 break :blk (try sema.resolveInstConst(block, .unneeded, ref)).val;6007 break :blk lib_name;
4464 } else null;6008 } else null;
44656009
4466 const abi_align = if (inst_data.flags.has_align) blk: {6010 const cc: std.builtin.CallingConvention = if (small.has_cc) blk: {
4467 const ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_i]);6011 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
4468 extra_i += 1;6012 extra_index += 1;
4469 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u32);6013 const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref);
4470 } else 0;6014 break :blk cc_tv.val.toEnum(cc_tv.ty, std.builtin.CallingConvention);
44716015 } else .Unspecified;
4472 const bit_start = if (inst_data.flags.has_bit_range) blk: {
4473 const ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_i]);
4474 extra_i += 1;
4475 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16);
4476 } else 0;
4477
4478 const bit_end = if (inst_data.flags.has_bit_range) blk: {
4479 const ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_i]);
4480 extra_i += 1;
4481 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16);
4482 } else 0;
4483
4484 if (bit_end != 0 and bit_start >= bit_end * 8)
4485 return sema.mod.fail(&block.base, src, "bit offset starts after end of host integer", .{});
44866016
4487 const elem_type = try sema.resolveType(block, .unneeded, extra.data.elem_type);6017 const align_val: Value = if (small.has_align) blk: {
6018 const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
6019 extra_index += 1;
6020 const align_tv = try sema.resolveInstConst(block, align_src, align_ref);
6021 break :blk align_tv.val;
6022 } else Value.initTag(.null_value);
6023
6024 const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
6025 extra_index += param_types.len;
6026
6027 var body_inst: Zir.Inst.Index = 0;
6028 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
6029 if (extra.data.body_len != 0) {
6030 body_inst = inst;
6031 extra_index += extra.data.body_len;
6032 src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
6033 }
44886034
4489 const ty = try sema.mod.ptrType(6035 return sema.funcCommon(
4490 sema.arena,6036 block,
4491 elem_type,6037 extra.data.src_node,
4492 sentinel,6038 param_types,
4493 abi_align,6039 body_inst,
4494 bit_start,6040 extra.data.return_type,
4495 bit_end,6041 cc,
4496 inst_data.flags.is_mutable,6042 align_val,
4497 inst_data.flags.is_allowzero,6043 small.is_var_args,
4498 inst_data.flags.is_volatile,6044 small.is_inferred_error,
4499 inst_data.size,6045 small.is_extern,
6046 src_locs,
6047 lib_name,
4500 );6048 );
4501 return sema.mod.constType(sema.arena, src, ty);
4502}6049}
45036050
4504fn zirStructInitEmpty(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {6051fn zirCUndef(
4505 const tracy = trace(@src());6052 sema: *Sema,
4506 defer tracy.end();6053 block: *Scope.Block,
6054 extended: Zir.Inst.Extended.InstData,
6055) InnerError!*Inst {
6056 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
6057 const src: LazySrcLoc = .{ .node_offset = extra.node };
6058 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCUndef", .{});
6059}
45076060
4508 const inst_data = sema.code.instructions.items(.data)[inst].un_node;6061fn zirCInclude(
4509 const src = inst_data.src();6062 sema: *Sema,
4510 const struct_type = try sema.resolveType(block, src, inst_data.operand);6063 block: *Scope.Block,
6064 extended: Zir.Inst.Extended.InstData,
6065) InnerError!*Inst {
6066 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
6067 const src: LazySrcLoc = .{ .node_offset = extra.node };
6068 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCInclude", .{});
6069}
45116070
4512 return sema.mod.constInst(sema.arena, src, .{6071fn zirCDefine(
4513 .ty = struct_type,6072 sema: *Sema,
4514 .val = Value.initTag(.empty_struct_value),6073 block: *Scope.Block,
4515 });6074 extended: Zir.Inst.Extended.InstData,
6075) InnerError!*Inst {
6076 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
6077 const src: LazySrcLoc = .{ .node_offset = extra.node };
6078 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCDefine", .{});
4516}6079}
45176080
4518fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {6081fn zirWasmMemorySize(
4519 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;6082 sema: *Sema,
4520 const src = inst_data.src();6083 block: *Scope.Block,
4521 return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInit", .{});6084 extended: Zir.Inst.Extended.InstData,
6085) InnerError!*Inst {
6086 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
6087 const src: LazySrcLoc = .{ .node_offset = extra.node };
6088 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirWasmMemorySize", .{});
4522}6089}
45236090
4524fn zirFieldType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {6091fn zirWasmMemoryGrow(
4525 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;6092 sema: *Sema,
4526 const src = inst_data.src();6093 block: *Scope.Block,
4527 return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldType", .{});6094 extended: Zir.Inst.Extended.InstData,
6095) InnerError!*Inst {
6096 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
6097 const src: LazySrcLoc = .{ .node_offset = extra.node };
6098 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirWasmMemoryGrow", .{});
6099}
6100
6101fn zirBuiltinExtern(
6102 sema: *Sema,
6103 block: *Scope.Block,
6104 extended: Zir.Inst.Extended.InstData,
6105) InnerError!*Inst {
6106 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
6107 const src: LazySrcLoc = .{ .node_offset = extra.node };
6108 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirBuiltinExtern", .{});
4528}6109}
45296110
4530fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {6111fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {
...@@ -4535,7 +6116,7 @@ fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void...@@ -4535,7 +6116,7 @@ fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void
45356116
4536fn requireRuntimeBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {6117fn requireRuntimeBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {
4537 if (block.is_comptime) {6118 if (block.is_comptime) {
4538 return sema.mod.fail(&block.base, src, "unable to resolve comptime value", .{});6119 return sema.failWithNeededComptime(block, src);
4539 }6120 }
4540 try sema.requireFunctionBlock(block, src);6121 try sema.requireFunctionBlock(block, src);
4541}6122}
...@@ -4611,7 +6192,7 @@ fn addSafetyCheck(sema: *Sema, parent_block: *Scope.Block, ok: *Inst, panic_id:...@@ -4611,7 +6192,7 @@ fn addSafetyCheck(sema: *Sema, parent_block: *Scope.Block, ok: *Inst, panic_id:
4611 try parent_block.instructions.append(sema.gpa, &block_inst.base);6192 try parent_block.instructions.append(sema.gpa, &block_inst.base);
4612}6193}
46136194
4614fn safetyPanic(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, panic_id: PanicId) !zir.Inst.Index {6195fn safetyPanic(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, panic_id: PanicId) !Zir.Inst.Index {
4615 // TODO Once we have a panic function to call, call it here instead of breakpoint.6196 // TODO Once we have a panic function to call, call it here instead of breakpoint.
4616 _ = try block.addNoOp(src, Type.initTag(.void), .breakpoint);6197 _ = try block.addNoOp(src, Type.initTag(.void), .breakpoint);
4617 _ = try block.addNoOp(src, Type.initTag(.noreturn), .unreach);6198 _ = try block.addNoOp(src, Type.initTag(.noreturn), .unreach);
...@@ -4719,21 +6300,9 @@ fn namedFieldPtr(...@@ -4719,21 +6300,9 @@ fn namedFieldPtr(
4719 });6300 });
4720 },6301 },
4721 .Struct, .Opaque, .Union => {6302 .Struct, .Opaque, .Union => {
4722 if (child_type.getContainerScope()) |container_scope| {6303 if (child_type.getNamespace()) |namespace| {
4723 if (mod.lookupDeclName(&container_scope.base, field_name)) |decl| {6304 if (try sema.analyzeNamespaceLookup(block, src, namespace, field_name)) |inst| {
4724 if (!decl.is_pub and !(decl.container.file_scope == block.base.namespace().file_scope))6305 return inst;
4725 return mod.fail(&block.base, src, "'{s}' is private", .{field_name});
4726 return sema.analyzeDeclRef(block, src, decl);
4727 }
4728
4729 // TODO this will give false positives for structs inside the root file
4730 if (container_scope.file_scope == mod.root_scope) {
4731 return mod.fail(
4732 &block.base,
4733 src,
4734 "root source file has no member named '{s}'",
4735 .{field_name},
4736 );
4737 }6306 }
4738 }6307 }
4739 // TODO add note: declared here6308 // TODO add note: declared here
...@@ -4748,11 +6317,9 @@ fn namedFieldPtr(...@@ -4748,11 +6317,9 @@ fn namedFieldPtr(
4748 });6317 });
4749 },6318 },
4750 .Enum => {6319 .Enum => {
4751 if (child_type.getContainerScope()) |container_scope| {6320 if (child_type.getNamespace()) |namespace| {
4752 if (mod.lookupDeclName(&container_scope.base, field_name)) |decl| {6321 if (try sema.analyzeNamespaceLookup(block, src, namespace, field_name)) |inst| {
4753 if (!decl.is_pub and !(decl.container.file_scope == block.base.namespace().file_scope))6322 return inst;
4754 return mod.fail(&block.base, src, "'{s}' is private", .{field_name});
4755 return sema.analyzeDeclRef(block, src, decl);
4756 }6323 }
4757 }6324 }
4758 const field_index = child_type.enumFieldIndex(field_name) orelse {6325 const field_index = child_type.enumFieldIndex(field_name) orelse {
...@@ -4785,11 +6352,38 @@ fn namedFieldPtr(...@@ -4785,11 +6352,38 @@ fn namedFieldPtr(
4785 }6352 }
4786 },6353 },
4787 .Struct => return sema.analyzeStructFieldPtr(block, src, object_ptr, field_name, field_name_src, elem_ty),6354 .Struct => return sema.analyzeStructFieldPtr(block, src, object_ptr, field_name, field_name_src, elem_ty),
6355 .Union => return sema.analyzeUnionFieldPtr(block, src, object_ptr, field_name, field_name_src, elem_ty),
4788 else => {},6356 else => {},
4789 }6357 }
4790 return mod.fail(&block.base, src, "type '{}' does not support field access", .{elem_ty});6358 return mod.fail(&block.base, src, "type '{}' does not support field access", .{elem_ty});
4791}6359}
47926360
6361fn analyzeNamespaceLookup(
6362 sema: *Sema,
6363 block: *Scope.Block,
6364 src: LazySrcLoc,
6365 namespace: *Scope.Namespace,
6366 decl_name: []const u8,
6367) InnerError!?*Inst {
6368 const mod = sema.mod;
6369 const gpa = sema.gpa;
6370 if (try sema.lookupInNamespace(namespace, decl_name)) |decl| {
6371 if (!decl.is_pub and decl.namespace.file_scope != block.getFileScope()) {
6372 const msg = msg: {
6373 const msg = try mod.errMsg(&block.base, src, "'{s}' is not marked 'pub'", .{
6374 decl_name,
6375 });
6376 errdefer msg.destroy(gpa);
6377 try mod.errNoteNonLazy(decl.srcLoc(), msg, "declared here", .{});
6378 break :msg msg;
6379 };
6380 return mod.failWithOwnedErrorMsg(&block.base, msg);
6381 }
6382 return try sema.analyzeDeclRef(block, src, decl);
6383 }
6384 return null;
6385}
6386
4793fn analyzeStructFieldPtr(6387fn analyzeStructFieldPtr(
4794 sema: *Sema,6388 sema: *Sema,
4795 block: *Scope.Block,6389 block: *Scope.Block,
...@@ -4797,23 +6391,71 @@ fn analyzeStructFieldPtr(...@@ -4797,23 +6391,71 @@ fn analyzeStructFieldPtr(
4797 struct_ptr: *Inst,6391 struct_ptr: *Inst,
4798 field_name: []const u8,6392 field_name: []const u8,
4799 field_name_src: LazySrcLoc,6393 field_name_src: LazySrcLoc,
4800 elem_ty: Type,6394 unresolved_struct_ty: Type,
4801) InnerError!*Inst {6395) InnerError!*Inst {
4802 const mod = sema.mod;6396 const mod = sema.mod;
4803 const arena = sema.arena;6397 const arena = sema.arena;
4804 assert(elem_ty.zigTypeTag() == .Struct);6398 assert(unresolved_struct_ty.zigTypeTag() == .Struct);
48056399
4806 const struct_obj = elem_ty.castTag(.@"struct").?.data;6400 const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);
6401 const struct_obj = struct_ty.castTag(.@"struct").?.data;
48076402
4808 const field_index = struct_obj.fields.getIndex(field_name) orelse6403 const field_index = struct_obj.fields.getIndex(field_name) orelse
4809 return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name);6404 return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name);
4810 const field = struct_obj.fields.entries.items[field_index].value;6405 const field = struct_obj.fields.entries.items[field_index].value;
4811 const ptr_field_ty = try mod.simplePtrType(arena, field.ty, true, .One);6406 const ptr_field_ty = try mod.simplePtrType(arena, field.ty, true, .One);
4812 // TODO comptime field access6407
6408 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
6409 return mod.constInst(arena, src, .{
6410 .ty = ptr_field_ty,
6411 .val = try Value.Tag.field_ptr.create(arena, .{
6412 .container_ptr = struct_ptr_val,
6413 .field_index = field_index,
6414 }),
6415 });
6416 }
6417
4813 try sema.requireRuntimeBlock(block, src);6418 try sema.requireRuntimeBlock(block, src);
4814 return block.addStructFieldPtr(src, ptr_field_ty, struct_ptr, @intCast(u32, field_index));6419 return block.addStructFieldPtr(src, ptr_field_ty, struct_ptr, @intCast(u32, field_index));
4815}6420}
48166421
6422fn analyzeUnionFieldPtr(
6423 sema: *Sema,
6424 block: *Scope.Block,
6425 src: LazySrcLoc,
6426 union_ptr: *Inst,
6427 field_name: []const u8,
6428 field_name_src: LazySrcLoc,
6429 unresolved_union_ty: Type,
6430) InnerError!*Inst {
6431 const mod = sema.mod;
6432 const arena = sema.arena;
6433 assert(unresolved_union_ty.zigTypeTag() == .Union);
6434
6435 const union_ty = try sema.resolveTypeFields(block, src, unresolved_union_ty);
6436 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
6437
6438 const field_index = union_obj.fields.getIndex(field_name) orelse
6439 return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name);
6440
6441 const field = union_obj.fields.entries.items[field_index].value;
6442 const ptr_field_ty = try mod.simplePtrType(arena, field.ty, true, .One);
6443
6444 if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| {
6445 // TODO detect inactive union field and emit compile error
6446 return mod.constInst(arena, src, .{
6447 .ty = ptr_field_ty,
6448 .val = try Value.Tag.field_ptr.create(arena, .{
6449 .container_ptr = union_ptr_val,
6450 .field_index = field_index,
6451 }),
6452 });
6453 }
6454
6455 try sema.requireRuntimeBlock(block, src);
6456 return mod.fail(&block.base, src, "TODO implement runtime union field access", .{});
6457}
6458
4817fn elemPtr(6459fn elemPtr(
4818 sema: *Sema,6460 sema: *Sema,
4819 block: *Scope.Block,6461 block: *Scope.Block,
...@@ -5003,17 +6645,18 @@ fn coerce(...@@ -5003,17 +6645,18 @@ fn coerce(
5003 if (inst.ty.zigTypeTag() == .EnumLiteral) {6645 if (inst.ty.zigTypeTag() == .EnumLiteral) {
5004 const val = try sema.resolveConstValue(block, inst_src, inst);6646 const val = try sema.resolveConstValue(block, inst_src, inst);
5005 const bytes = val.castTag(.enum_literal).?.data;6647 const bytes = val.castTag(.enum_literal).?.data;
5006 const field_index = dest_type.enumFieldIndex(bytes) orelse {6648 const resolved_dest_type = try sema.resolveTypeFields(block, inst_src, dest_type);
6649 const field_index = resolved_dest_type.enumFieldIndex(bytes) orelse {
5007 const msg = msg: {6650 const msg = msg: {
5008 const msg = try mod.errMsg(6651 const msg = try mod.errMsg(
5009 &block.base,6652 &block.base,
5010 inst_src,6653 inst_src,
5011 "enum '{}' has no field named '{s}'",6654 "enum '{}' has no field named '{s}'",
5012 .{ dest_type, bytes },6655 .{ resolved_dest_type, bytes },
5013 );6656 );
5014 errdefer msg.destroy(sema.gpa);6657 errdefer msg.destroy(sema.gpa);
5015 try mod.errNoteNonLazy(6658 try mod.errNoteNonLazy(
5016 dest_type.declSrcLoc(),6659 resolved_dest_type.declSrcLoc(),
5017 msg,6660 msg,
5018 "enum declared here",6661 "enum declared here",
5019 .{},6662 .{},
...@@ -5023,7 +6666,7 @@ fn coerce(...@@ -5023,7 +6666,7 @@ fn coerce(
5023 return mod.failWithOwnedErrorMsg(&block.base, msg);6666 return mod.failWithOwnedErrorMsg(&block.base, msg);
5024 };6667 };
5025 return mod.constInst(arena, inst_src, .{6668 return mod.constInst(arena, inst_src, .{
5026 .ty = dest_type,6669 .ty = resolved_dest_type,
5027 .val = try Value.Tag.enum_field_index.create(arena, @intCast(u32, field_index)),6670 .val = try Value.Tag.enum_field_index.create(arena, @intCast(u32, field_index)),
5028 });6671 });
5029 }6672 }
...@@ -5107,7 +6750,7 @@ fn storePtr(...@@ -5107,7 +6750,7 @@ fn storePtr(
51076750
5108 const elem_ty = ptr.ty.elemType();6751 const elem_ty = ptr.ty.elemType();
5109 const value = try sema.coerce(block, elem_ty, uncasted_value, src);6752 const value = try sema.coerce(block, elem_ty, uncasted_value, src);
5110 if (elem_ty.onePossibleValue() != null)6753 if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null)
5111 return;6754 return;
51126755
5113 // TODO handle comptime pointer writes6756 // TODO handle comptime pointer writes
...@@ -5149,7 +6792,7 @@ fn analyzeDeclVal(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl...@@ -5149,7 +6792,7 @@ fn analyzeDeclVal(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl
5149}6792}
51506793
5151fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst {6794fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst {
5152 _ = try sema.mod.declareDeclDependency(sema.owner_decl, decl);6795 try sema.mod.declareDeclDependency(sema.owner_decl, decl);
5153 sema.mod.ensureDeclAnalyzed(decl) catch |err| {6796 sema.mod.ensureDeclAnalyzed(decl) catch |err| {
5154 if (sema.func) |func| {6797 if (sema.func) |func| {
5155 func.state = .dependency_failure;6798 func.state = .dependency_failure;
...@@ -5202,7 +6845,7 @@ fn analyzeRef(...@@ -5202,7 +6845,7 @@ fn analyzeRef(
5202) InnerError!*Inst {6845) InnerError!*Inst {
5203 const ptr_type = try sema.mod.simplePtrType(sema.arena, operand.ty, false, .One);6846 const ptr_type = try sema.mod.simplePtrType(sema.arena, operand.ty, false, .One);
52046847
5205 if (operand.value()) |val| {6848 if (try sema.resolvePossiblyUndefinedValue(block, src, operand)) |val| {
5206 return sema.mod.constInst(sema.arena, src, .{6849 return sema.mod.constInst(sema.arena, src, .{
5207 .ty = ptr_type,6850 .ty = ptr_type,
5208 .val = try Value.Tag.ref_val.create(sema.arena, val),6851 .val = try Value.Tag.ref_val.create(sema.arena, val),
...@@ -5224,10 +6867,10 @@ fn analyzeLoad(...@@ -5224,10 +6867,10 @@ fn analyzeLoad(
5224 .Pointer => ptr.ty.elemType(),6867 .Pointer => ptr.ty.elemType(),
5225 else => return sema.mod.fail(&block.base, ptr_src, "expected pointer, found '{}'", .{ptr.ty}),6868 else => return sema.mod.fail(&block.base, ptr_src, "expected pointer, found '{}'", .{ptr.ty}),
5226 };6869 };
5227 if (ptr.value()) |val| {6870 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
5228 return sema.mod.constInst(sema.arena, src, .{6871 return sema.mod.constInst(sema.arena, src, .{
5229 .ty = elem_ty,6872 .ty = elem_ty,
5230 .val = try val.pointerDeref(sema.arena),6873 .val = try ptr_val.pointerDeref(sema.arena),
5231 });6874 });
5232 }6875 }
52336876
...@@ -5242,14 +6885,18 @@ fn analyzeIsNull(...@@ -5242,14 +6885,18 @@ fn analyzeIsNull(
5242 operand: *Inst,6885 operand: *Inst,
5243 invert_logic: bool,6886 invert_logic: bool,
5244) InnerError!*Inst {6887) InnerError!*Inst {
5245 if (operand.value()) |opt_val| {6888 const result_ty = Type.initTag(.bool);
6889 if (try sema.resolvePossiblyUndefinedValue(block, src, operand)) |opt_val| {
6890 if (opt_val.isUndef()) {
6891 return sema.mod.constUndef(sema.arena, src, result_ty);
6892 }
5246 const is_null = opt_val.isNull();6893 const is_null = opt_val.isNull();
5247 const bool_value = if (invert_logic) !is_null else is_null;6894 const bool_value = if (invert_logic) !is_null else is_null;
5248 return sema.mod.constBool(sema.arena, src, bool_value);6895 return sema.mod.constBool(sema.arena, src, bool_value);
5249 }6896 }
5250 try sema.requireRuntimeBlock(block, src);6897 try sema.requireRuntimeBlock(block, src);
5251 const inst_tag: Inst.Tag = if (invert_logic) .is_non_null else .is_null;6898 const inst_tag: Inst.Tag = if (invert_logic) .is_non_null else .is_null;
5252 return block.addUnOp(src, Type.initTag(.bool), inst_tag, operand);6899 return block.addUnOp(src, result_ty, inst_tag, operand);
5253}6900}
52546901
5255fn analyzeIsErr(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, operand: *Inst) InnerError!*Inst {6902fn analyzeIsErr(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, operand: *Inst) InnerError!*Inst {
...@@ -5257,11 +6904,15 @@ fn analyzeIsErr(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, operand: *Ins...@@ -5257,11 +6904,15 @@ fn analyzeIsErr(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, operand: *Ins
5257 if (ot != .ErrorSet and ot != .ErrorUnion) return sema.mod.constBool(sema.arena, src, false);6904 if (ot != .ErrorSet and ot != .ErrorUnion) return sema.mod.constBool(sema.arena, src, false);
5258 if (ot == .ErrorSet) return sema.mod.constBool(sema.arena, src, true);6905 if (ot == .ErrorSet) return sema.mod.constBool(sema.arena, src, true);
5259 assert(ot == .ErrorUnion);6906 assert(ot == .ErrorUnion);
5260 if (operand.value()) |err_union| {6907 const result_ty = Type.initTag(.bool);
6908 if (try sema.resolvePossiblyUndefinedValue(block, src, operand)) |err_union| {
6909 if (err_union.isUndef()) {
6910 return sema.mod.constUndef(sema.arena, src, result_ty);
6911 }
5261 return sema.mod.constBool(sema.arena, src, err_union.getError() != null);6912 return sema.mod.constBool(sema.arena, src, err_union.getError() != null);
5262 }6913 }
5263 try sema.requireRuntimeBlock(block, src);6914 try sema.requireRuntimeBlock(block, src);
5264 return block.addUnOp(src, Type.initTag(.bool), .is_err, operand);6915 return block.addUnOp(src, result_ty, .is_err, operand);
5265}6916}
52666917
5267fn analyzeSlice(6918fn analyzeSlice(
...@@ -5338,65 +6989,6 @@ fn analyzeSlice(...@@ -5338,65 +6989,6 @@ fn analyzeSlice(
5338 return sema.mod.fail(&block.base, src, "TODO implement analysis of slice", .{});6989 return sema.mod.fail(&block.base, src, "TODO implement analysis of slice", .{});
5339}6990}
53406991
5341fn analyzeImport(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, target_string: []const u8) !*Scope.File {
5342 const cur_pkg = block.getFileScope().pkg;
5343 const cur_pkg_dir_path = cur_pkg.root_src_directory.path orelse ".";
5344 const found_pkg = cur_pkg.table.get(target_string);
5345
5346 const resolved_path = if (found_pkg) |pkg|
5347 try std.fs.path.resolve(sema.gpa, &[_][]const u8{ pkg.root_src_directory.path orelse ".", pkg.root_src_path })
5348 else
5349 try std.fs.path.resolve(sema.gpa, &[_][]const u8{ cur_pkg_dir_path, target_string });
5350 errdefer sema.gpa.free(resolved_path);
5351
5352 if (sema.mod.import_table.get(resolved_path)) |cached_import| {
5353 sema.gpa.free(resolved_path);
5354 return cached_import;
5355 }
5356
5357 if (found_pkg == null) {
5358 const resolved_root_path = try std.fs.path.resolve(sema.gpa, &[_][]const u8{cur_pkg_dir_path});
5359 defer sema.gpa.free(resolved_root_path);
5360
5361 if (!mem.startsWith(u8, resolved_path, resolved_root_path)) {
5362 return error.ImportOutsidePkgPath;
5363 }
5364 }
5365
5366 // TODO Scope.Container arena for ty and sub_file_path
5367 const file_scope = try sema.gpa.create(Scope.File);
5368 errdefer sema.gpa.destroy(file_scope);
5369 const struct_ty = try Type.Tag.empty_struct.create(sema.gpa, &file_scope.root_container);
5370 errdefer sema.gpa.destroy(struct_ty.castTag(.empty_struct).?);
5371
5372 const container_name_hash: Scope.NameHash = if (found_pkg) |pkg|
5373 pkg.namespace_hash
5374 else
5375 std.zig.hashName(cur_pkg.namespace_hash, "/", resolved_path);
5376
5377 file_scope.* = .{
5378 .sub_file_path = resolved_path,
5379 .source = .{ .unloaded = {} },
5380 .tree = undefined,
5381 .status = .never_loaded,
5382 .pkg = found_pkg orelse cur_pkg,
5383 .root_container = .{
5384 .file_scope = file_scope,
5385 .decls = .{},
5386 .ty = struct_ty,
5387 .parent_name_hash = container_name_hash,
5388 },
5389 };
5390 sema.mod.analyzeContainer(&file_scope.root_container) catch |err| switch (err) {
5391 error.AnalysisFail => {
5392 assert(sema.mod.comp.totalErrorCount() != 0);
5393 },
5394 else => |e| return e,
5395 };
5396 try sema.mod.import_table.put(sema.gpa, file_scope.sub_file_path, file_scope);
5397 return file_scope;
5398}
5399
5400/// Asserts that lhs and rhs types are both numeric.6992/// Asserts that lhs and rhs types are both numeric.
5401fn cmpNumeric(6993fn cmpNumeric(
5402 sema: *Sema,6994 sema: *Sema,
...@@ -5696,9 +7288,299 @@ fn resolvePeerTypes(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, instructi...@@ -5696,9 +7288,299 @@ fn resolvePeerTypes(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, instructi
5696 continue;7288 continue;
5697 }7289 }
56987290
7291 if (chosen.ty.zigTypeTag() == .Enum and candidate.ty.zigTypeTag() == .EnumLiteral) {
7292 continue;
7293 }
7294 if (chosen.ty.zigTypeTag() == .EnumLiteral and candidate.ty.zigTypeTag() == .Enum) {
7295 chosen = candidate;
7296 continue;
7297 }
7298
5699 // TODO error notes pointing out each type7299 // TODO error notes pointing out each type
5700 return sema.mod.fail(&block.base, src, "incompatible types: '{}' and '{}'", .{ chosen.ty, candidate.ty });7300 return sema.mod.fail(&block.base, src, "incompatible types: '{}' and '{}'", .{ chosen.ty, candidate.ty });
5701 }7301 }
57027302
5703 return chosen.ty;7303 return chosen.ty;
5704}7304}
7305
7306fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type) InnerError!Type {
7307 switch (ty.tag()) {
7308 .@"struct" => {
7309 const struct_obj = ty.castTag(.@"struct").?.data;
7310 switch (struct_obj.status) {
7311 .none => {},
7312 .field_types_wip => {
7313 return sema.mod.fail(&block.base, src, "struct {} depends on itself", .{
7314 ty,
7315 });
7316 },
7317 .have_field_types, .have_layout, .layout_wip => return ty,
7318 }
7319 struct_obj.status = .field_types_wip;
7320 try sema.mod.analyzeStructFields(struct_obj);
7321 struct_obj.status = .have_field_types;
7322 return ty;
7323 },
7324 .extern_options => return sema.resolveBuiltinTypeFields(block, src, ty, "ExternOptions"),
7325 .export_options => return sema.resolveBuiltinTypeFields(block, src, ty, "ExportOptions"),
7326 .atomic_ordering => return sema.resolveBuiltinTypeFields(block, src, ty, "AtomicOrdering"),
7327 .atomic_rmw_op => return sema.resolveBuiltinTypeFields(block, src, ty, "AtomicRmwOp"),
7328 .calling_convention => return sema.resolveBuiltinTypeFields(block, src, ty, "CallingConvention"),
7329 .float_mode => return sema.resolveBuiltinTypeFields(block, src, ty, "FloatMode"),
7330 .reduce_op => return sema.resolveBuiltinTypeFields(block, src, ty, "ReduceOp"),
7331 .call_options => return sema.resolveBuiltinTypeFields(block, src, ty, "CallOptions"),
7332
7333 .@"union", .union_tagged => {
7334 const union_obj = ty.cast(Type.Payload.Union).?.data;
7335 switch (union_obj.status) {
7336 .none => {},
7337 .field_types_wip => {
7338 return sema.mod.fail(&block.base, src, "union {} depends on itself", .{
7339 ty,
7340 });
7341 },
7342 .have_field_types, .have_layout, .layout_wip => return ty,
7343 }
7344 union_obj.status = .field_types_wip;
7345 try sema.mod.analyzeUnionFields(union_obj);
7346 union_obj.status = .have_field_types;
7347 return ty;
7348 },
7349 else => return ty,
7350 }
7351}
7352
7353fn resolveBuiltinTypeFields(
7354 sema: *Sema,
7355 block: *Scope.Block,
7356 src: LazySrcLoc,
7357 ty: Type,
7358 name: []const u8,
7359) InnerError!Type {
7360 const resolved_ty = try sema.getBuiltinType(block, src, name);
7361 return sema.resolveTypeFields(block, src, resolved_ty);
7362}
7363
7364fn getBuiltinType(
7365 sema: *Sema,
7366 block: *Scope.Block,
7367 src: LazySrcLoc,
7368 name: []const u8,
7369) InnerError!Type {
7370 const mod = sema.mod;
7371 const std_pkg = mod.root_pkg.table.get("std").?;
7372 const std_file = (mod.importPkg(mod.root_pkg, std_pkg) catch unreachable).file;
7373 const opt_builtin_inst = try sema.analyzeNamespaceLookup(
7374 block,
7375 src,
7376 std_file.root_decl.?.namespace,
7377 "builtin",
7378 );
7379 const builtin_inst = try sema.analyzeLoad(block, src, opt_builtin_inst.?, src);
7380 const builtin_ty = try sema.resolveAirAsType(block, src, builtin_inst);
7381 const opt_ty_inst = try sema.analyzeNamespaceLookup(
7382 block,
7383 src,
7384 builtin_ty.getNamespace().?,
7385 name,
7386 );
7387 const ty_inst = try sema.analyzeLoad(block, src, opt_ty_inst.?, src);
7388 return sema.resolveAirAsType(block, src, ty_inst);
7389}
7390
7391/// There is another implementation of this in `Type.onePossibleValue`. This one
7392/// in `Sema` is for calling during semantic analysis, and peforms field resolution
7393/// to get the answer. The one in `Type` is for calling during codegen and asserts
7394/// that the types are already resolved.
7395fn typeHasOnePossibleValue(
7396 sema: *Sema,
7397 block: *Scope.Block,
7398 src: LazySrcLoc,
7399 starting_type: Type,
7400) InnerError!?Value {
7401 var ty = starting_type;
7402 while (true) switch (ty.tag()) {
7403 .f16,
7404 .f32,
7405 .f64,
7406 .f128,
7407 .c_longdouble,
7408 .comptime_int,
7409 .comptime_float,
7410 .u8,
7411 .i8,
7412 .u16,
7413 .i16,
7414 .u32,
7415 .i32,
7416 .u64,
7417 .i64,
7418 .u128,
7419 .i128,
7420 .usize,
7421 .isize,
7422 .c_short,
7423 .c_ushort,
7424 .c_int,
7425 .c_uint,
7426 .c_long,
7427 .c_ulong,
7428 .c_longlong,
7429 .c_ulonglong,
7430 .bool,
7431 .type,
7432 .anyerror,
7433 .fn_noreturn_no_args,
7434 .fn_void_no_args,
7435 .fn_naked_noreturn_no_args,
7436 .fn_ccc_void_no_args,
7437 .function,
7438 .single_const_pointer_to_comptime_int,
7439 .array_sentinel,
7440 .array_u8_sentinel_0,
7441 .const_slice_u8,
7442 .const_slice,
7443 .mut_slice,
7444 .c_void,
7445 .optional,
7446 .optional_single_mut_pointer,
7447 .optional_single_const_pointer,
7448 .enum_literal,
7449 .anyerror_void_error_union,
7450 .error_union,
7451 .error_set,
7452 .error_set_single,
7453 .@"opaque",
7454 .var_args_param,
7455 .manyptr_u8,
7456 .manyptr_const_u8,
7457 .atomic_ordering,
7458 .atomic_rmw_op,
7459 .calling_convention,
7460 .float_mode,
7461 .reduce_op,
7462 .call_options,
7463 .export_options,
7464 .extern_options,
7465 .@"anyframe",
7466 .anyframe_T,
7467 .many_const_pointer,
7468 .many_mut_pointer,
7469 .c_const_pointer,
7470 .c_mut_pointer,
7471 .single_const_pointer,
7472 .single_mut_pointer,
7473 .pointer,
7474 => return null,
7475
7476 .@"struct" => {
7477 const resolved_ty = try sema.resolveTypeFields(block, src, ty);
7478 const s = resolved_ty.castTag(.@"struct").?.data;
7479 for (s.fields.entries.items) |entry| {
7480 const field_ty = entry.value.ty;
7481 if ((try sema.typeHasOnePossibleValue(block, src, field_ty)) == null) {
7482 return null;
7483 }
7484 }
7485 return Value.initTag(.empty_struct_value);
7486 },
7487 .enum_full => {
7488 const resolved_ty = try sema.resolveTypeFields(block, src, ty);
7489 const enum_full = resolved_ty.castTag(.enum_full).?.data;
7490 if (enum_full.fields.count() == 1) {
7491 return enum_full.values.entries.items[0].key;
7492 } else {
7493 return null;
7494 }
7495 },
7496 .enum_simple => {
7497 const resolved_ty = try sema.resolveTypeFields(block, src, ty);
7498 const enum_simple = resolved_ty.castTag(.enum_simple).?.data;
7499 if (enum_simple.fields.count() == 1) {
7500 return Value.initTag(.zero);
7501 } else {
7502 return null;
7503 }
7504 },
7505 .enum_nonexhaustive => ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty,
7506 .@"union" => {
7507 return null; // TODO
7508 },
7509 .union_tagged => {
7510 return null; // TODO
7511 },
7512
7513 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
7514 .void => return Value.initTag(.void_value),
7515 .noreturn => return Value.initTag(.unreachable_value),
7516 .@"null" => return Value.initTag(.null_value),
7517 .@"undefined" => return Value.initTag(.undef),
7518
7519 .int_unsigned, .int_signed => {
7520 if (ty.cast(Type.Payload.Bits).?.data == 0) {
7521 return Value.initTag(.zero);
7522 } else {
7523 return null;
7524 }
7525 },
7526 .vector, .array, .array_u8 => {
7527 if (ty.arrayLen() == 0)
7528 return Value.initTag(.empty_array);
7529 ty = ty.elemType();
7530 continue;
7531 },
7532
7533 .inferred_alloc_const => unreachable,
7534 .inferred_alloc_mut => unreachable,
7535 };
7536}
7537
7538fn getAstTree(sema: *Sema, block: *Scope.Block) InnerError!*const std.zig.ast.Tree {
7539 return block.src_decl.namespace.file_scope.getTree(sema.gpa) catch |err| {
7540 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
7541 return error.AnalysisFail;
7542 };
7543}
7544
7545fn enumFieldSrcLoc(
7546 decl: *Decl,
7547 tree: std.zig.ast.Tree,
7548 node_offset: i32,
7549 field_index: usize,
7550) LazySrcLoc {
7551 @setCold(true);
7552 const enum_node = decl.relativeToNodeIndex(node_offset);
7553 const node_tags = tree.nodes.items(.tag);
7554 var buffer: [2]std.zig.ast.Node.Index = undefined;
7555 const container_decl = switch (node_tags[enum_node]) {
7556 .container_decl,
7557 .container_decl_trailing,
7558 => tree.containerDecl(enum_node),
7559
7560 .container_decl_two,
7561 .container_decl_two_trailing,
7562 => tree.containerDeclTwo(&buffer, enum_node),
7563
7564 .container_decl_arg,
7565 .container_decl_arg_trailing,
7566 => tree.containerDeclArg(enum_node),
7567
7568 else => unreachable,
7569 };
7570 var it_index: usize = 0;
7571 for (container_decl.ast.members) |member_node| {
7572 switch (node_tags[member_node]) {
7573 .container_field_init,
7574 .container_field_align,
7575 .container_field,
7576 => {
7577 if (it_index == field_index) {
7578 return .{ .node_offset = decl.nodeIndexToRelative(member_node) };
7579 }
7580 it_index += 1;
7581 },
7582
7583 else => continue,
7584 }
7585 } else unreachable;
7586}
src/Zir.zig created+4810
...@@ -0,0 +1,4810 @@
1//! Zig Intermediate Representation. Astgen.zig converts AST nodes to these
2//! untyped IR instructions. Next, Sema.zig processes these into TZIR.
3//! The minimum amount of information needed to represent a list of ZIR instructions.
4//! Once this structure is completed, it can be used to generate TZIR, followed by
5//! machine code, without any memory access into the AST tree token list, node list,
6//! or source bytes. Exceptions include:
7//! * Compile errors, which may need to reach into these data structures to
8//! create a useful report.
9//! * In the future, possibly inline assembly, which needs to get parsed and
10//! handled by the codegen backend, and errors reported there. However for now,
11//! inline assembly is not an exception.
12
13const std = @import("std");
14const mem = std.mem;
15const Allocator = std.mem.Allocator;
16const assert = std.debug.assert;
17const BigIntConst = std.math.big.int.Const;
18const BigIntMutable = std.math.big.int.Mutable;
19const ast = std.zig.ast;
20
21const Zir = @This();
22const Type = @import("type.zig").Type;
23const Value = @import("value.zig").Value;
24const TypedValue = @import("TypedValue.zig");
25const ir = @import("ir.zig");
26const Module = @import("Module.zig");
27const LazySrcLoc = Module.LazySrcLoc;
28
29instructions: std.MultiArrayList(Inst).Slice,
30/// In order to store references to strings in fewer bytes, we copy all
31/// string bytes into here. String bytes can be null. It is up to whomever
32/// is referencing the data here whether they want to store both index and length,
33/// thus allowing null bytes, or store only index, and use null-termination. The
34/// `string_bytes` array is agnostic to either usage.
35/// Indexes 0 and 1 are reserved for special cases.
36string_bytes: []u8,
37/// The meaning of this data is determined by `Inst.Tag` value.
38/// The first few indexes are reserved. See `ExtraIndex` for the values.
39extra: []u32,
40
41/// The data stored at byte offset 0 when ZIR is stored in a file.
42pub const Header = extern struct {
43 instructions_len: u32,
44 string_bytes_len: u32,
45 extra_len: u32,
46
47 stat_inode: std.fs.File.INode,
48 stat_size: u64,
49 stat_mtime: i128,
50};
51
52pub const ExtraIndex = enum(u32) {
53 /// Ref. The main struct decl for this file.
54 main_struct,
55 /// If this is 0, no compile errors. Otherwise there is a `CompileErrors`
56 /// payload at this index.
57 compile_errors,
58 /// If this is 0, this file contains no imports. Otherwise there is a `Imports`
59 /// payload at this index.
60 imports,
61
62 _,
63};
64
65pub fn getMainStruct(zir: Zir) Zir.Inst.Index {
66 return zir.extra[@enumToInt(ExtraIndex.main_struct)] -
67 @intCast(u32, Inst.Ref.typed_value_map.len);
68}
69
70/// Returns the requested data, as well as the new index which is at the start of the
71/// trailers for the object.
72pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, end: usize } {
73 const fields = std.meta.fields(T);
74 var i: usize = index;
75 var result: T = undefined;
76 inline for (fields) |field| {
77 @field(result, field.name) = switch (field.field_type) {
78 u32 => code.extra[i],
79 Inst.Ref => @intToEnum(Inst.Ref, code.extra[i]),
80 i32 => @bitCast(i32, code.extra[i]),
81 else => @compileError("bad field type"),
82 };
83 i += 1;
84 }
85 return .{
86 .data = result,
87 .end = i,
88 };
89}
90
91/// Given an index into `string_bytes` returns the null-terminated string found there.
92pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 {
93 var end: usize = index;
94 while (code.string_bytes[end] != 0) {
95 end += 1;
96 }
97 return code.string_bytes[index..end :0];
98}
99
100pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {
101 const raw_slice = code.extra[start..][0..len];
102 return @bitCast([]Inst.Ref, raw_slice);
103}
104
105pub fn hasCompileErrors(code: Zir) bool {
106 return code.extra[@enumToInt(ExtraIndex.compile_errors)] != 0;
107}
108
109pub fn deinit(code: *Zir, gpa: *Allocator) void {
110 code.instructions.deinit(gpa);
111 gpa.free(code.string_bytes);
112 gpa.free(code.extra);
113 code.* = undefined;
114}
115
116/// Write human-readable, debug formatted ZIR code to a file.
117pub fn renderAsTextToFile(
118 gpa: *Allocator,
119 scope_file: *Module.Scope.File,
120 fs_file: std.fs.File,
121) !void {
122 var arena = std.heap.ArenaAllocator.init(gpa);
123 defer arena.deinit();
124
125 var writer: Writer = .{
126 .gpa = gpa,
127 .arena = &arena.allocator,
128 .file = scope_file,
129 .code = scope_file.zir,
130 .indent = 0,
131 .parent_decl_node = 0,
132 };
133
134 const main_struct_inst = scope_file.zir.getMainStruct();
135 try fs_file.writer().print("%{d} ", .{main_struct_inst});
136 try writer.writeInstToStream(fs_file.writer(), main_struct_inst);
137 try fs_file.writeAll("\n");
138 const imports_index = scope_file.zir.extra[@enumToInt(ExtraIndex.imports)];
139 if (imports_index != 0) {
140 try fs_file.writeAll("Imports:\n");
141 const imports_len = scope_file.zir.extra[imports_index];
142 for (scope_file.zir.extra[imports_index + 1 ..][0..imports_len]) |str_index| {
143 const import_path = scope_file.zir.nullTerminatedString(str_index);
144 try fs_file.writer().print(" {s}\n", .{import_path});
145 }
146 }
147}
148
149/// These are untyped instructions generated from an Abstract Syntax Tree.
150/// The data here is immutable because it is possible to have multiple
151/// analyses on the same ZIR happening at the same time.
152pub const Inst = struct {
153 tag: Tag,
154 data: Data,
155
156 /// These names are used directly as the instruction names in the text format.
157 /// See `data_field_map` for a list of which `Data` fields are used by each `Tag`.
158 pub const Tag = enum(u8) {
159 /// Arithmetic addition, asserts no integer overflow.
160 /// Uses the `pl_node` union field. Payload is `Bin`.
161 add,
162 /// Twos complement wrapping integer addition.
163 /// Uses the `pl_node` union field. Payload is `Bin`.
164 addwrap,
165 /// Declares a parameter of the current function. Used for debug info and
166 /// for checking shadowing against declarations in the current namespace.
167 /// Uses the `str_tok` field. Token is the parameter name, string is the
168 /// parameter name.
169 arg,
170 /// Array concatenation. `a ++ b`
171 /// Uses the `pl_node` union field. Payload is `Bin`.
172 array_cat,
173 /// Array multiplication `a ** b`
174 /// Uses the `pl_node` union field. Payload is `Bin`.
175 array_mul,
176 /// `[N]T` syntax. No source location provided.
177 /// Uses the `bin` union field. lhs is length, rhs is element type.
178 array_type,
179 /// `[N:S]T` syntax. No source location provided.
180 /// Uses the `array_type_sentinel` field.
181 array_type_sentinel,
182 /// `@Vector` builtin.
183 /// Uses the `pl_node` union field with `Bin` payload.
184 /// lhs is length, rhs is element type.
185 vector_type,
186 /// Given an array type, returns the element type.
187 /// Uses the `un_node` union field.
188 elem_type,
189 /// Given a pointer to an indexable object, returns the len property. This is
190 /// used by for loops. This instruction also emits a for-loop specific compile
191 /// error if the indexable object is not indexable.
192 /// Uses the `un_node` field. The AST node is the for loop node.
193 indexable_ptr_len,
194 /// Create a `anyframe->T` type.
195 /// Uses the `un_node` field.
196 anyframe_type,
197 /// Type coercion. No source location attached.
198 /// Uses the `bin` field.
199 as,
200 /// Type coercion to the function's return type.
201 /// Uses the `pl_node` field. Payload is `As`. AST node could be many things.
202 as_node,
203 /// Bitwise AND. `&`
204 bit_and,
205 /// Bitcast a value to a different type.
206 /// Uses the pl_node field with payload `Bin`.
207 bitcast,
208 /// A typed result location pointer is bitcasted to a new result location pointer.
209 /// The new result location pointer has an inferred type.
210 /// Uses the pl_node field with payload `Bin`.
211 bitcast_result_ptr,
212 /// Bitwise NOT. `~`
213 /// Uses `un_node`.
214 bit_not,
215 /// Bitwise OR. `|`
216 bit_or,
217 /// A labeled block of code, which can return a value.
218 /// Uses the `pl_node` union field. Payload is `Block`.
219 block,
220 /// A list of instructions which are analyzed in the parent context, without
221 /// generating a runtime block. Must terminate with an "inline" variant of
222 /// a noreturn instruction.
223 /// Uses the `pl_node` union field. Payload is `Block`.
224 block_inline,
225 /// Implements `suspend {...}`.
226 /// Uses the `pl_node` union field. Payload is `Block`.
227 suspend_block,
228 /// Boolean AND. See also `bit_and`.
229 /// Uses the `pl_node` union field. Payload is `Bin`.
230 bool_and,
231 /// Boolean NOT. See also `bit_not`.
232 /// Uses the `un_node` field.
233 bool_not,
234 /// Boolean OR. See also `bit_or`.
235 /// Uses the `pl_node` union field. Payload is `Bin`.
236 bool_or,
237 /// Short-circuiting boolean `and`. `lhs` is a boolean `Ref` and the other operand
238 /// is a block, which is evaluated if `lhs` is `true`.
239 /// Uses the `bool_br` union field.
240 bool_br_and,
241 /// Short-circuiting boolean `or`. `lhs` is a boolean `Ref` and the other operand
242 /// is a block, which is evaluated if `lhs` is `false`.
243 /// Uses the `bool_br` union field.
244 bool_br_or,
245 /// Return a value from a block.
246 /// Uses the `break` union field.
247 /// Uses the source information from previous instruction.
248 @"break",
249 /// Return a value from a block. This instruction is used as the terminator
250 /// of a `block_inline`. It allows using the return value from `Sema.analyzeBody`.
251 /// This instruction may also be used when it is known that there is only one
252 /// break instruction in a block, and the target block is the parent.
253 /// Uses the `break` union field.
254 break_inline,
255 /// Uses the `node` union field.
256 breakpoint,
257 /// Function call with modifier `.auto`.
258 /// Uses `pl_node`. AST node is the function call. Payload is `Call`.
259 call,
260 /// Same as `call` but it also does `ensure_result_used` on the return value.
261 call_chkused,
262 /// Same as `call` but with modifier `.compile_time`.
263 call_compile_time,
264 /// Same as `call` but with modifier `.no_suspend`.
265 call_nosuspend,
266 /// Same as `call` but with modifier `.async_kw`.
267 call_async,
268 /// `<`
269 /// Uses the `pl_node` union field. Payload is `Bin`.
270 cmp_lt,
271 /// `<=`
272 /// Uses the `pl_node` union field. Payload is `Bin`.
273 cmp_lte,
274 /// `==`
275 /// Uses the `pl_node` union field. Payload is `Bin`.
276 cmp_eq,
277 /// `>=`
278 /// Uses the `pl_node` union field. Payload is `Bin`.
279 cmp_gte,
280 /// `>`
281 /// Uses the `pl_node` union field. Payload is `Bin`.
282 cmp_gt,
283 /// `!=`
284 /// Uses the `pl_node` union field. Payload is `Bin`.
285 cmp_neq,
286 /// Coerces a result location pointer to a new element type. It is evaluated "backwards"-
287 /// as type coercion from the new element type to the old element type.
288 /// Uses the `bin` union field.
289 /// LHS is destination element type, RHS is result pointer.
290 coerce_result_ptr,
291 /// Conditional branch. Splits control flow based on a boolean condition value.
292 /// Uses the `pl_node` union field. AST node is an if, while, for, etc.
293 /// Payload is `CondBr`.
294 condbr,
295 /// Same as `condbr`, except the condition is coerced to a comptime value, and
296 /// only the taken branch is analyzed. The then block and else block must
297 /// terminate with an "inline" variant of a noreturn instruction.
298 condbr_inline,
299 /// An opaque type definition. Provides an AST node only.
300 /// Uses the `pl_node` union field. Payload is `OpaqueDecl`.
301 opaque_decl,
302 opaque_decl_anon,
303 opaque_decl_func,
304 /// An error set type definition. Contains a list of field names.
305 /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.
306 error_set_decl,
307 error_set_decl_anon,
308 error_set_decl_func,
309 /// Declares the beginning of a statement. Used for debug info.
310 /// Uses the `dbg_stmt` union field. The line and column are offset
311 /// from the parent declaration.
312 dbg_stmt,
313 /// Uses a name to identify a Decl and takes a pointer to it.
314 /// Uses the `str_tok` union field.
315 decl_ref,
316 /// Uses a name to identify a Decl and uses it as a value.
317 /// Uses the `str_tok` union field.
318 decl_val,
319 /// Load the value from a pointer. Assumes `x.*` syntax.
320 /// Uses `un_node` field. AST node is the `x.*` syntax.
321 load,
322 /// Arithmetic division. Asserts no integer overflow.
323 /// Uses the `pl_node` union field. Payload is `Bin`.
324 div,
325 /// Given a pointer to an array, slice, or pointer, returns a pointer to the element at
326 /// the provided index. Uses the `bin` union field. Source location is implied
327 /// to be the same as the previous instruction.
328 elem_ptr,
329 /// Same as `elem_ptr` except also stores a source location node.
330 /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
331 elem_ptr_node,
332 /// Given an array, slice, or pointer, returns the element at the provided index.
333 /// Uses the `bin` union field. Source location is implied to be the same
334 /// as the previous instruction.
335 elem_val,
336 /// Same as `elem_val` except also stores a source location node.
337 /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
338 elem_val_node,
339 /// Emits a compile error if the operand is not `void`.
340 /// Uses the `un_node` field.
341 ensure_result_used,
342 /// Emits a compile error if an error is ignored.
343 /// Uses the `un_node` field.
344 ensure_result_non_error,
345 /// Create a `E!T` type.
346 /// Uses the `pl_node` field with `Bin` payload.
347 error_union_type,
348 /// `error.Foo` syntax. Uses the `str_tok` field of the Data union.
349 error_value,
350 /// Implements the `@export` builtin function.
351 /// Uses the `pl_node` union field. Payload is `Bin`.
352 @"export",
353 /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
354 /// to the named field. The field name is stored in string_bytes. Used by a.b syntax.
355 /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field.
356 field_ptr,
357 /// Given a struct or object that contains virtual fields, returns the named field.
358 /// The field name is stored in string_bytes. Used by a.b syntax.
359 /// This instruction also accepts a pointer.
360 /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field.
361 field_val,
362 /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
363 /// to the named field. The field name is a comptime instruction. Used by @field.
364 /// Uses `pl_node` field. The AST node is the builtin call. Payload is FieldNamed.
365 field_ptr_named,
366 /// Given a struct or object that contains virtual fields, returns the named field.
367 /// The field name is a comptime instruction. Used by @field.
368 /// Uses `pl_node` field. The AST node is the builtin call. Payload is FieldNamed.
369 field_val_named,
370 /// Returns a function type, or a function instance, depending on whether
371 /// the body_len is 0. Calling convention is auto.
372 /// Uses the `pl_node` union field. `payload_index` points to a `Func`.
373 func,
374 /// Same as `func` but has an inferred error set.
375 func_inferred,
376 /// Implements the `@import` builtin.
377 /// Uses the `str_tok` field.
378 import,
379 /// Integer literal that fits in a u64. Uses the `int` union field.
380 int,
381 /// Arbitrary sized integer literal. Uses the `str` union field.
382 int_big,
383 /// A float literal that fits in a f32. Uses the float union value.
384 float,
385 /// A float literal that fits in a f128. Uses the `pl_node` union value.
386 /// Payload is `Float128`.
387 float128,
388 /// Make an integer type out of signedness and bit count.
389 /// Payload is `int_type`
390 int_type,
391 /// Return a boolean false if an optional is null. `x != null`
392 /// Uses the `un_node` field.
393 is_non_null,
394 /// Return a boolean true if an optional is null. `x == null`
395 /// Uses the `un_node` field.
396 is_null,
397 /// Return a boolean false if an optional is null. `x.* != null`
398 /// Uses the `un_node` field.
399 is_non_null_ptr,
400 /// Return a boolean true if an optional is null. `x.* == null`
401 /// Uses the `un_node` field.
402 is_null_ptr,
403 /// Return a boolean true if value is an error
404 /// Uses the `un_node` field.
405 is_err,
406 /// Return a boolean true if dereferenced pointer is an error
407 /// Uses the `un_node` field.
408 is_err_ptr,
409 /// A labeled block of code that loops forever. At the end of the body will have either
410 /// a `repeat` instruction or a `repeat_inline` instruction.
411 /// Uses the `pl_node` field. The AST node is either a for loop or while loop.
412 /// This ZIR instruction is needed because TZIR does not (yet?) match ZIR, and Sema
413 /// needs to emit more than 1 TZIR block for this instruction.
414 /// The payload is `Block`.
415 loop,
416 /// Sends runtime control flow back to the beginning of the current block.
417 /// Uses the `node` field.
418 repeat,
419 /// Sends comptime control flow back to the beginning of the current block.
420 /// Uses the `node` field.
421 repeat_inline,
422 /// Merge two error sets into one, `E1 || E2`.
423 /// Uses the `pl_node` field with payload `Bin`.
424 merge_error_sets,
425 /// Ambiguously remainder division or modulus. If the computation would possibly have
426 /// a different value depending on whether the operation is remainder division or modulus,
427 /// a compile error is emitted. Otherwise the computation is performed.
428 /// Uses the `pl_node` union field. Payload is `Bin`.
429 mod_rem,
430 /// Arithmetic multiplication. Asserts no integer overflow.
431 /// Uses the `pl_node` union field. Payload is `Bin`.
432 mul,
433 /// Twos complement wrapping integer multiplication.
434 /// Uses the `pl_node` union field. Payload is `Bin`.
435 mulwrap,
436 /// Given a reference to a function and a parameter index, returns the
437 /// type of the parameter. The only usage of this instruction is for the
438 /// result location of parameters of function calls. In the case of a function's
439 /// parameter type being `anytype`, it is the type coercion's job to detect this
440 /// scenario and skip the coercion, so that semantic analysis of this instruction
441 /// is not in a position where it must create an invalid type.
442 /// Uses the `param_type` union field.
443 param_type,
444 /// Turns an R-Value into a const L-Value. In other words, it takes a value,
445 /// stores it in a memory location, and returns a const pointer to it. If the value
446 /// is `comptime`, the memory location is global static constant data. Otherwise,
447 /// the memory location is in the stack frame, local to the scope containing the
448 /// instruction.
449 /// Uses the `un_tok` union field.
450 ref,
451 /// Sends control flow back to the function's callee.
452 /// Includes an operand as the return value.
453 /// Includes an AST node source location.
454 /// Uses the `un_node` union field.
455 ret_node,
456 /// Sends control flow back to the function's callee.
457 /// Includes an operand as the return value.
458 /// Includes a token source location.
459 /// Uses the `un_tok` union field.
460 /// The operand needs to get coerced to the function's return type.
461 ret_coerce,
462 /// Create a pointer type that does not have a sentinel, alignment, or bit range specified.
463 /// Uses the `ptr_type_simple` union field.
464 ptr_type_simple,
465 /// Create a pointer type which can have a sentinel, alignment, and/or bit range.
466 /// Uses the `ptr_type` union field.
467 ptr_type,
468 /// Slice operation `lhs[rhs..]`. No sentinel and no end offset.
469 /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceStart`.
470 slice_start,
471 /// Slice operation `array_ptr[start..end]`. No sentinel.
472 /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceEnd`.
473 slice_end,
474 /// Slice operation `array_ptr[start..end:sentinel]`.
475 /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceSentinel`.
476 slice_sentinel,
477 /// Write a value to a pointer. For loading, see `load`.
478 /// Source location is assumed to be same as previous instruction.
479 /// Uses the `bin` union field.
480 store,
481 /// Same as `store` except provides a source location.
482 /// Uses the `pl_node` union field. Payload is `Bin`.
483 store_node,
484 /// Same as `store` but the type of the value being stored will be used to infer
485 /// the block type. The LHS is the pointer to store to.
486 /// Uses the `bin` union field.
487 /// If the pointer is none, it means this instruction has been elided in
488 /// AstGen, but AstGen was unable to actually omit it from the ZIR code.
489 store_to_block_ptr,
490 /// Same as `store` but the type of the value being stored will be used to infer
491 /// the pointer type.
492 /// Uses the `bin` union field - Astgen.zig depends on the ability to change
493 /// the tag of an instruction from `store_to_block_ptr` to `store_to_inferred_ptr`
494 /// without changing the data.
495 store_to_inferred_ptr,
496 /// String Literal. Makes an anonymous Decl and then takes a pointer to it.
497 /// Uses the `str` union field.
498 str,
499 /// Arithmetic subtraction. Asserts no integer overflow.
500 /// Uses the `pl_node` union field. Payload is `Bin`.
501 sub,
502 /// Twos complement wrapping integer subtraction.
503 /// Uses the `pl_node` union field. Payload is `Bin`.
504 subwrap,
505 /// Arithmetic negation. Asserts no integer overflow.
506 /// Same as sub with a lhs of 0, split into a separate instruction to save memory.
507 /// Uses `un_node`.
508 negate,
509 /// Twos complement wrapping integer negation.
510 /// Same as subwrap with a lhs of 0, split into a separate instruction to save memory.
511 /// Uses `un_node`.
512 negate_wrap,
513 /// Returns the type of a value.
514 /// Uses the `un_node` field.
515 typeof,
516 /// Given a value which is a pointer, returns the element type.
517 /// Uses the `un_node` field.
518 typeof_elem,
519 /// Given a value, look at the type of it, which must be an integer type.
520 /// Returns the integer type for the RHS of a shift operation.
521 /// Uses the `un_node` field.
522 typeof_log2_int_type,
523 /// Given an integer type, returns the integer type for the RHS of a shift operation.
524 /// Uses the `un_node` field.
525 log2_int_type,
526 /// Asserts control-flow will not reach this instruction (`unreachable`).
527 /// Uses the `unreachable` union field.
528 @"unreachable",
529 /// Bitwise XOR. `^`
530 /// Uses the `pl_node` union field. Payload is `Bin`.
531 xor,
532 /// Create an optional type '?T'
533 /// Uses the `un_node` field.
534 optional_type,
535 /// ?T => T with safety.
536 /// Given an optional value, returns the payload value, with a safety check that
537 /// the value is non-null. Used for `orelse`, `if` and `while`.
538 /// Uses the `un_node` field.
539 optional_payload_safe,
540 /// ?T => T without safety.
541 /// Given an optional value, returns the payload value. No safety checks.
542 /// Uses the `un_node` field.
543 optional_payload_unsafe,
544 /// *?T => *T with safety.
545 /// Given a pointer to an optional value, returns a pointer to the payload value,
546 /// with a safety check that the value is non-null. Used for `orelse`, `if` and `while`.
547 /// Uses the `un_node` field.
548 optional_payload_safe_ptr,
549 /// *?T => *T without safety.
550 /// Given a pointer to an optional value, returns a pointer to the payload value.
551 /// No safety checks.
552 /// Uses the `un_node` field.
553 optional_payload_unsafe_ptr,
554 /// E!T => T with safety.
555 /// Given an error union value, returns the payload value, with a safety check
556 /// that the value is not an error. Used for catch, if, and while.
557 /// Uses the `un_node` field.
558 err_union_payload_safe,
559 /// E!T => T without safety.
560 /// Given an error union value, returns the payload value. No safety checks.
561 /// Uses the `un_node` field.
562 err_union_payload_unsafe,
563 /// *E!T => *T with safety.
564 /// Given a pointer to an error union value, returns a pointer to the payload value,
565 /// with a safety check that the value is not an error. Used for catch, if, and while.
566 /// Uses the `un_node` field.
567 err_union_payload_safe_ptr,
568 /// *E!T => *T without safety.
569 /// Given a pointer to a error union value, returns a pointer to the payload value.
570 /// No safety checks.
571 /// Uses the `un_node` field.
572 err_union_payload_unsafe_ptr,
573 /// E!T => E without safety.
574 /// Given an error union value, returns the error code. No safety checks.
575 /// Uses the `un_node` field.
576 err_union_code,
577 /// *E!T => E without safety.
578 /// Given a pointer to an error union value, returns the error code. No safety checks.
579 /// Uses the `un_node` field.
580 err_union_code_ptr,
581 /// Takes a *E!T and raises a compiler error if T != void
582 /// Uses the `un_tok` field.
583 ensure_err_payload_void,
584 /// An enum literal. Uses the `str_tok` union field.
585 enum_literal,
586 /// A switch expression. Uses the `pl_node` union field.
587 /// AST node is the switch, payload is `SwitchBlock`.
588 /// All prongs of target handled.
589 switch_block,
590 /// Same as switch_block, except one or more prongs have multiple items.
591 /// Payload is `SwitchBlockMulti`
592 switch_block_multi,
593 /// Same as switch_block, except has an else prong.
594 switch_block_else,
595 /// Same as switch_block_else, except one or more prongs have multiple items.
596 /// Payload is `SwitchBlockMulti`
597 switch_block_else_multi,
598 /// Same as switch_block, except has an underscore prong.
599 switch_block_under,
600 /// Same as switch_block, except one or more prongs have multiple items.
601 /// Payload is `SwitchBlockMulti`
602 switch_block_under_multi,
603 /// Same as `switch_block` but the target is a pointer to the value being switched on.
604 switch_block_ref,
605 /// Same as `switch_block_multi` but the target is a pointer to the value being switched on.
606 /// Payload is `SwitchBlockMulti`
607 switch_block_ref_multi,
608 /// Same as `switch_block_else` but the target is a pointer to the value being switched on.
609 switch_block_ref_else,
610 /// Same as `switch_block_else_multi` but the target is a pointer to the
611 /// value being switched on.
612 /// Payload is `SwitchBlockMulti`
613 switch_block_ref_else_multi,
614 /// Same as `switch_block_under` but the target is a pointer to the value
615 /// being switched on.
616 switch_block_ref_under,
617 /// Same as `switch_block_under_multi` but the target is a pointer to
618 /// the value being switched on.
619 /// Payload is `SwitchBlockMulti`
620 switch_block_ref_under_multi,
621 /// Produces the capture value for a switch prong.
622 /// Uses the `switch_capture` field.
623 switch_capture,
624 /// Produces the capture value for a switch prong.
625 /// Result is a pointer to the value.
626 /// Uses the `switch_capture` field.
627 switch_capture_ref,
628 /// Produces the capture value for a switch prong.
629 /// The prong is one of the multi cases.
630 /// Uses the `switch_capture` field.
631 switch_capture_multi,
632 /// Produces the capture value for a switch prong.
633 /// The prong is one of the multi cases.
634 /// Result is a pointer to the value.
635 /// Uses the `switch_capture` field.
636 switch_capture_multi_ref,
637 /// Produces the capture value for the else/'_' switch prong.
638 /// Uses the `switch_capture` field.
639 switch_capture_else,
640 /// Produces the capture value for the else/'_' switch prong.
641 /// Result is a pointer to the value.
642 /// Uses the `switch_capture` field.
643 switch_capture_else_ref,
644 /// Given a set of `field_ptr` instructions, assumes they are all part of a struct
645 /// initialization expression, and emits compile errors for duplicate fields
646 /// as well as missing fields, if applicable.
647 /// This instruction asserts that there is at least one field_ptr instruction,
648 /// because it must use one of them to find out the struct type.
649 /// Uses the `pl_node` field. Payload is `Block`.
650 validate_struct_init_ptr,
651 /// Given a set of `elem_ptr_node` instructions, assumes they are all part of an
652 /// array initialization expression, and emits a compile error if the number of
653 /// elements does not match the array type.
654 /// This instruction asserts that there is at least one elem_ptr_node instruction,
655 /// because it must use one of them to find out the array type.
656 /// Uses the `pl_node` field. Payload is `Block`.
657 validate_array_init_ptr,
658 /// A struct literal with a specified type, with no fields.
659 /// Uses the `un_node` field.
660 struct_init_empty,
661 /// Given a struct, union, or enum, and a field name as a string index,
662 /// returns the field type. Uses the `pl_node` field. Payload is `FieldType`.
663 field_type,
664 /// Given a struct, union, or enum, and a field name as a Ref,
665 /// returns the field type. Uses the `pl_node` field. Payload is `FieldTypeRef`.
666 field_type_ref,
667 /// Finalizes a typed struct initialization, performs validation, and returns the
668 /// struct value.
669 /// Uses the `pl_node` field. Payload is `StructInit`.
670 struct_init,
671 /// Struct initialization syntax, make the result a pointer.
672 /// Uses the `pl_node` field. Payload is `StructInit`.
673 struct_init_ref,
674 /// Struct initialization without a type.
675 /// Uses the `pl_node` field. Payload is `StructInitAnon`.
676 struct_init_anon,
677 /// Anonymous struct initialization syntax, make the result a pointer.
678 /// Uses the `pl_node` field. Payload is `StructInitAnon`.
679 struct_init_anon_ref,
680 /// Array initialization syntax.
681 /// Uses the `pl_node` field. Payload is `MultiOp`.
682 array_init,
683 /// Anonymous array initialization syntax.
684 /// Uses the `pl_node` field. Payload is `MultiOp`.
685 array_init_anon,
686 /// Array initialization syntax, make the result a pointer.
687 /// Uses the `pl_node` field. Payload is `MultiOp`.
688 array_init_ref,
689 /// Anonymous array initialization syntax, make the result a pointer.
690 /// Uses the `pl_node` field. Payload is `MultiOp`.
691 array_init_anon_ref,
692 /// Given a pointer to a union and a comptime known field name, activates that field
693 /// and returns a pointer to it.
694 /// Uses the `pl_node` field. Payload is `UnionInitPtr`.
695 union_init_ptr,
696 /// Implements the `@typeInfo` builtin. Uses `un_node`.
697 type_info,
698 /// Implements the `@sizeOf` builtin. Uses `un_node`.
699 size_of,
700 /// Implements the `@bitSizeOf` builtin. Uses `un_node`.
701 bit_size_of,
702 /// Implements the `@fence` builtin. Uses `node`.
703 fence,
704
705 /// Implement builtin `@ptrToInt`. Uses `un_node`.
706 /// Convert a pointer to a `usize` integer.
707 ptr_to_int,
708 /// Implement builtin `@errToInt`. Uses `un_node`.
709 error_to_int,
710 /// Implement builtin `@intToError`. Uses `un_node`.
711 int_to_error,
712 /// Emit an error message and fail compilation.
713 /// Uses the `un_node` field.
714 compile_error,
715 /// Changes the maximum number of backwards branches that compile-time
716 /// code execution can use before giving up and making a compile error.
717 /// Uses the `un_node` union field.
718 set_eval_branch_quota,
719 /// Converts an enum value into an integer. Resulting type will be the tag type
720 /// of the enum. Uses `un_node`.
721 enum_to_int,
722 /// Implement builtin `@alignOf`. Uses `un_node`.
723 align_of,
724 /// Implement builtin `@boolToInt`. Uses `un_node`.
725 bool_to_int,
726 /// Implement builtin `@embedFile`. Uses `un_node`.
727 embed_file,
728 /// Implement builtin `@errorName`. Uses `un_node`.
729 error_name,
730 /// Implement builtin `@panic`. Uses `un_node`.
731 panic,
732 /// Implement builtin `@setAlignStack`. Uses `un_node`.
733 set_align_stack,
734 /// Implement builtin `@setCold`. Uses `un_node`.
735 set_cold,
736 /// Implement builtin `@setFloatMode`. Uses `un_node`.
737 set_float_mode,
738 /// Implement builtin `@setRuntimeSafety`. Uses `un_node`.
739 set_runtime_safety,
740 /// Implement builtin `@sqrt`. Uses `un_node`.
741 sqrt,
742 /// Implement builtin `@sin`. Uses `un_node`.
743 sin,
744 /// Implement builtin `@cos`. Uses `un_node`.
745 cos,
746 /// Implement builtin `@exp`. Uses `un_node`.
747 exp,
748 /// Implement builtin `@exp2`. Uses `un_node`.
749 exp2,
750 /// Implement builtin `@log`. Uses `un_node`.
751 log,
752 /// Implement builtin `@log2`. Uses `un_node`.
753 log2,
754 /// Implement builtin `@log10`. Uses `un_node`.
755 log10,
756 /// Implement builtin `@fabs`. Uses `un_node`.
757 fabs,
758 /// Implement builtin `@floor`. Uses `un_node`.
759 floor,
760 /// Implement builtin `@ceil`. Uses `un_node`.
761 ceil,
762 /// Implement builtin `@trunc`. Uses `un_node`.
763 trunc,
764 /// Implement builtin `@round`. Uses `un_node`.
765 round,
766 /// Implement builtin `@tagName`. Uses `un_node`.
767 tag_name,
768 /// Implement builtin `@Type`. Uses `un_node`.
769 reify,
770 /// Implement builtin `@typeName`. Uses `un_node`.
771 type_name,
772 /// Implement builtin `@Frame`. Uses `un_node`.
773 frame_type,
774 /// Implement builtin `@frameSize`. Uses `un_node`.
775 frame_size,
776
777 /// Implements the `@floatToInt` builtin.
778 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
779 float_to_int,
780 /// Implements the `@intToFloat` builtin.
781 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
782 int_to_float,
783 /// Implements the `@intToPtr` builtin.
784 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
785 int_to_ptr,
786 /// Converts an integer into an enum value.
787 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
788 int_to_enum,
789 /// Convert a larger float type to any other float type, possibly causing
790 /// a loss of precision.
791 /// Uses the `pl_node` field. AST is the `@floatCast` syntax.
792 /// Payload is `Bin` with lhs as the dest type, rhs the operand.
793 float_cast,
794 /// Implements the `@intCast` builtin.
795 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
796 /// Convert an integer value to another integer type, asserting that the destination type
797 /// can hold the same mathematical value.
798 int_cast,
799 /// Implements the `@errSetCast` builtin.
800 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
801 err_set_cast,
802 /// Implements the `@ptrCast` builtin.
803 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
804 ptr_cast,
805 /// Implements the `@truncate` builtin.
806 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
807 truncate,
808 /// Implements the `@alignCast` builtin.
809 /// Uses `pl_node` with payload `Bin`. `lhs` is dest alignment, `rhs` is operand.
810 align_cast,
811
812 /// Implements the `@hasDecl` builtin.
813 /// Uses the `pl_node` union field. Payload is `Bin`.
814 has_decl,
815 /// Implements the `@hasField` builtin.
816 /// Uses the `pl_node` union field. Payload is `Bin`.
817 has_field,
818
819 /// Implements the `@clz` builtin. Uses the `un_node` union field.
820 clz,
821 /// Implements the `@ctz` builtin. Uses the `un_node` union field.
822 ctz,
823 /// Implements the `@popCount` builtin. Uses the `un_node` union field.
824 pop_count,
825 /// Implements the `@byteSwap` builtin. Uses the `un_node` union field.
826 byte_swap,
827 /// Implements the `@bitReverse` builtin. Uses the `un_node` union field.
828 bit_reverse,
829
830 /// Implements the `@divExact` builtin.
831 /// Uses the `pl_node` union field with payload `Bin`.
832 div_exact,
833 /// Implements the `@divFloor` builtin.
834 /// Uses the `pl_node` union field with payload `Bin`.
835 div_floor,
836 /// Implements the `@divTrunc` builtin.
837 /// Uses the `pl_node` union field with payload `Bin`.
838 div_trunc,
839 /// Implements the `@mod` builtin.
840 /// Uses the `pl_node` union field with payload `Bin`.
841 mod,
842 /// Implements the `@rem` builtin.
843 /// Uses the `pl_node` union field with payload `Bin`.
844 rem,
845
846 /// Integer shift-left. Zeroes are shifted in from the right hand side.
847 /// Uses the `pl_node` union field. Payload is `Bin`.
848 shl,
849 /// Implements the `@shlExact` builtin.
850 /// Uses the `pl_node` union field with payload `Bin`.
851 shl_exact,
852 /// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type.
853 /// Uses the `pl_node` union field. Payload is `Bin`.
854 shr,
855 /// Implements the `@shrExact` builtin.
856 /// Uses the `pl_node` union field with payload `Bin`.
857 shr_exact,
858
859 /// Implements the `@bitOffsetOf` builtin.
860 /// Uses the `pl_node` union field with payload `Bin`.
861 bit_offset_of,
862 /// Implements the `@byteOffsetOf` builtin.
863 /// Uses the `pl_node` union field with payload `Bin`.
864 byte_offset_of,
865 /// Implements the `@cmpxchgStrong` builtin.
866 /// Uses the `pl_node` union field with payload `Cmpxchg`.
867 cmpxchg_strong,
868 /// Implements the `@cmpxchgWeak` builtin.
869 /// Uses the `pl_node` union field with payload `Cmpxchg`.
870 cmpxchg_weak,
871 /// Implements the `@splat` builtin.
872 /// Uses the `pl_node` union field with payload `Bin`.
873 splat,
874 /// Implements the `@reduce` builtin.
875 /// Uses the `pl_node` union field with payload `Bin`.
876 reduce,
877 /// Implements the `@shuffle` builtin.
878 /// Uses the `pl_node` union field with payload `Shuffle`.
879 shuffle,
880 /// Implements the `@atomicLoad` builtin.
881 /// Uses the `pl_node` union field with payload `Bin`.
882 atomic_load,
883 /// Implements the `@atomicRmw` builtin.
884 /// Uses the `pl_node` union field with payload `AtomicRmw`.
885 atomic_rmw,
886 /// Implements the `@atomicStore` builtin.
887 /// Uses the `pl_node` union field with payload `AtomicStore`.
888 atomic_store,
889 /// Implements the `@mulAdd` builtin.
890 /// Uses the `pl_node` union field with payload `MulAdd`.
891 mul_add,
892 /// Implements the `@call` builtin.
893 /// Uses the `pl_node` union field with payload `BuiltinCall`.
894 builtin_call,
895 /// Given a type and a field name, returns a pointer to the field type.
896 /// Assumed to be part of a `@fieldParentPtr` builtin call.
897 /// Uses the `bin` union field. LHS is type, RHS is field name.
898 field_ptr_type,
899 /// Implements the `@fieldParentPtr` builtin.
900 /// Uses the `pl_node` union field with payload `FieldParentPtr`.
901 field_parent_ptr,
902 /// Implements the `@memcpy` builtin.
903 /// Uses the `pl_node` union field with payload `Memcpy`.
904 memcpy,
905 /// Implements the `@memset` builtin.
906 /// Uses the `pl_node` union field with payload `Memset`.
907 memset,
908 /// Implements the `@asyncCall` builtin.
909 /// Uses the `pl_node` union field with payload `AsyncCall`.
910 builtin_async_call,
911 /// Implements the `@cImport` builtin.
912 /// Uses the `pl_node` union field with payload `Block`.
913 c_import,
914
915 /// Allocates stack local memory.
916 /// Uses the `un_node` union field. The operand is the type of the allocated object.
917 /// The node source location points to a var decl node.
918 alloc,
919 /// Same as `alloc` except mutable.
920 alloc_mut,
921 /// Allocates comptime-mutable memory.
922 /// Uses the `un_node` union field. The operand is the type of the allocated object.
923 /// The node source location points to a var decl node.
924 alloc_comptime,
925 /// Same as `alloc` except the type is inferred.
926 /// Uses the `node` union field.
927 alloc_inferred,
928 /// Same as `alloc_inferred` except mutable.
929 alloc_inferred_mut,
930 /// Same as `alloc_comptime` except the type is inferred.
931 alloc_inferred_comptime,
932 /// Each `store_to_inferred_ptr` puts the type of the stored value into a set,
933 /// and then `resolve_inferred_alloc` triggers peer type resolution on the set.
934 /// The operand is a `alloc_inferred` or `alloc_inferred_mut` instruction, which
935 /// is the allocation that needs to have its type inferred.
936 /// Uses the `un_node` field. The AST node is the var decl.
937 resolve_inferred_alloc,
938
939 /// Implements `resume` syntax. Uses `un_node` field.
940 @"resume",
941 @"await",
942 await_nosuspend,
943
944 /// The ZIR instruction tag is one of the `Extended` ones.
945 /// Uses the `extended` union field.
946 extended,
947
948 /// Returns whether the instruction is one of the control flow "noreturn" types.
949 /// Function calls do not count.
950 pub fn isNoReturn(tag: Tag) bool {
951 return switch (tag) {
952 .arg,
953 .add,
954 .addwrap,
955 .alloc,
956 .alloc_mut,
957 .alloc_comptime,
958 .alloc_inferred,
959 .alloc_inferred_mut,
960 .alloc_inferred_comptime,
961 .array_cat,
962 .array_mul,
963 .array_type,
964 .array_type_sentinel,
965 .vector_type,
966 .elem_type,
967 .indexable_ptr_len,
968 .anyframe_type,
969 .as,
970 .as_node,
971 .bit_and,
972 .bitcast,
973 .bitcast_result_ptr,
974 .bit_or,
975 .block,
976 .block_inline,
977 .suspend_block,
978 .loop,
979 .bool_br_and,
980 .bool_br_or,
981 .bool_not,
982 .bool_and,
983 .bool_or,
984 .breakpoint,
985 .fence,
986 .call,
987 .call_chkused,
988 .call_compile_time,
989 .call_nosuspend,
990 .call_async,
991 .cmp_lt,
992 .cmp_lte,
993 .cmp_eq,
994 .cmp_gte,
995 .cmp_gt,
996 .cmp_neq,
997 .coerce_result_ptr,
998 .opaque_decl,
999 .opaque_decl_anon,
1000 .opaque_decl_func,
1001 .error_set_decl,
1002 .error_set_decl_anon,
1003 .error_set_decl_func,
1004 .dbg_stmt,
1005 .decl_ref,
1006 .decl_val,
1007 .load,
1008 .div,
1009 .elem_ptr,
1010 .elem_val,
1011 .elem_ptr_node,
1012 .elem_val_node,
1013 .ensure_result_used,
1014 .ensure_result_non_error,
1015 .@"export",
1016 .field_ptr,
1017 .field_val,
1018 .field_ptr_named,
1019 .field_val_named,
1020 .func,
1021 .func_inferred,
1022 .has_decl,
1023 .int,
1024 .int_big,
1025 .float,
1026 .float128,
1027 .int_type,
1028 .is_non_null,
1029 .is_null,
1030 .is_non_null_ptr,
1031 .is_null_ptr,
1032 .is_err,
1033 .is_err_ptr,
1034 .mod_rem,
1035 .mul,
1036 .mulwrap,
1037 .param_type,
1038 .ref,
1039 .shl,
1040 .shr,
1041 .store,
1042 .store_node,
1043 .store_to_block_ptr,
1044 .store_to_inferred_ptr,
1045 .str,
1046 .sub,
1047 .subwrap,
1048 .negate,
1049 .negate_wrap,
1050 .typeof,
1051 .typeof_elem,
1052 .xor,
1053 .optional_type,
1054 .optional_payload_safe,
1055 .optional_payload_unsafe,
1056 .optional_payload_safe_ptr,
1057 .optional_payload_unsafe_ptr,
1058 .err_union_payload_safe,
1059 .err_union_payload_unsafe,
1060 .err_union_payload_safe_ptr,
1061 .err_union_payload_unsafe_ptr,
1062 .err_union_code,
1063 .err_union_code_ptr,
1064 .error_to_int,
1065 .int_to_error,
1066 .ptr_type,
1067 .ptr_type_simple,
1068 .ensure_err_payload_void,
1069 .enum_literal,
1070 .merge_error_sets,
1071 .error_union_type,
1072 .bit_not,
1073 .error_value,
1074 .slice_start,
1075 .slice_end,
1076 .slice_sentinel,
1077 .import,
1078 .typeof_log2_int_type,
1079 .log2_int_type,
1080 .resolve_inferred_alloc,
1081 .set_eval_branch_quota,
1082 .switch_capture,
1083 .switch_capture_ref,
1084 .switch_capture_multi,
1085 .switch_capture_multi_ref,
1086 .switch_capture_else,
1087 .switch_capture_else_ref,
1088 .switch_block,
1089 .switch_block_multi,
1090 .switch_block_else,
1091 .switch_block_else_multi,
1092 .switch_block_under,
1093 .switch_block_under_multi,
1094 .switch_block_ref,
1095 .switch_block_ref_multi,
1096 .switch_block_ref_else,
1097 .switch_block_ref_else_multi,
1098 .switch_block_ref_under,
1099 .switch_block_ref_under_multi,
1100 .validate_struct_init_ptr,
1101 .validate_array_init_ptr,
1102 .struct_init_empty,
1103 .struct_init,
1104 .struct_init_ref,
1105 .struct_init_anon,
1106 .struct_init_anon_ref,
1107 .array_init,
1108 .array_init_anon,
1109 .array_init_ref,
1110 .array_init_anon_ref,
1111 .union_init_ptr,
1112 .field_type,
1113 .field_type_ref,
1114 .int_to_enum,
1115 .enum_to_int,
1116 .type_info,
1117 .size_of,
1118 .bit_size_of,
1119 .ptr_to_int,
1120 .align_of,
1121 .bool_to_int,
1122 .embed_file,
1123 .error_name,
1124 .set_align_stack,
1125 .set_cold,
1126 .set_float_mode,
1127 .set_runtime_safety,
1128 .sqrt,
1129 .sin,
1130 .cos,
1131 .exp,
1132 .exp2,
1133 .log,
1134 .log2,
1135 .log10,
1136 .fabs,
1137 .floor,
1138 .ceil,
1139 .trunc,
1140 .round,
1141 .tag_name,
1142 .reify,
1143 .type_name,
1144 .frame_type,
1145 .frame_size,
1146 .float_to_int,
1147 .int_to_float,
1148 .int_to_ptr,
1149 .float_cast,
1150 .int_cast,
1151 .err_set_cast,
1152 .ptr_cast,
1153 .truncate,
1154 .align_cast,
1155 .has_field,
1156 .clz,
1157 .ctz,
1158 .pop_count,
1159 .byte_swap,
1160 .bit_reverse,
1161 .div_exact,
1162 .div_floor,
1163 .div_trunc,
1164 .mod,
1165 .rem,
1166 .shl_exact,
1167 .shr_exact,
1168 .bit_offset_of,
1169 .byte_offset_of,
1170 .cmpxchg_strong,
1171 .cmpxchg_weak,
1172 .splat,
1173 .reduce,
1174 .shuffle,
1175 .atomic_load,
1176 .atomic_rmw,
1177 .atomic_store,
1178 .mul_add,
1179 .builtin_call,
1180 .field_ptr_type,
1181 .field_parent_ptr,
1182 .memcpy,
1183 .memset,
1184 .builtin_async_call,
1185 .c_import,
1186 .@"resume",
1187 .@"await",
1188 .await_nosuspend,
1189 .extended,
1190 => false,
1191
1192 .@"break",
1193 .break_inline,
1194 .condbr,
1195 .condbr_inline,
1196 .compile_error,
1197 .ret_node,
1198 .ret_coerce,
1199 .@"unreachable",
1200 .repeat,
1201 .repeat_inline,
1202 .panic,
1203 => true,
1204 };
1205 }
1206
1207 /// Used by debug safety-checking code.
1208 pub const data_tags = list: {
1209 @setEvalBranchQuota(2000);
1210 break :list std.enums.directEnumArray(Tag, Data.FieldEnum, 0, .{
1211 .add = .pl_node,
1212 .addwrap = .pl_node,
1213 .arg = .str_tok,
1214 .array_cat = .pl_node,
1215 .array_mul = .pl_node,
1216 .array_type = .bin,
1217 .array_type_sentinel = .array_type_sentinel,
1218 .vector_type = .pl_node,
1219 .elem_type = .un_node,
1220 .indexable_ptr_len = .un_node,
1221 .anyframe_type = .un_node,
1222 .as = .bin,
1223 .as_node = .pl_node,
1224 .bit_and = .pl_node,
1225 .bitcast = .pl_node,
1226 .bitcast_result_ptr = .pl_node,
1227 .bit_not = .un_node,
1228 .bit_or = .pl_node,
1229 .block = .pl_node,
1230 .block_inline = .pl_node,
1231 .suspend_block = .pl_node,
1232 .bool_and = .pl_node,
1233 .bool_not = .un_node,
1234 .bool_or = .pl_node,
1235 .bool_br_and = .bool_br,
1236 .bool_br_or = .bool_br,
1237 .@"break" = .@"break",
1238 .break_inline = .@"break",
1239 .breakpoint = .node,
1240 .call = .pl_node,
1241 .call_chkused = .pl_node,
1242 .call_compile_time = .pl_node,
1243 .call_nosuspend = .pl_node,
1244 .call_async = .pl_node,
1245 .cmp_lt = .pl_node,
1246 .cmp_lte = .pl_node,
1247 .cmp_eq = .pl_node,
1248 .cmp_gte = .pl_node,
1249 .cmp_gt = .pl_node,
1250 .cmp_neq = .pl_node,
1251 .coerce_result_ptr = .bin,
1252 .condbr = .pl_node,
1253 .condbr_inline = .pl_node,
1254 .opaque_decl = .pl_node,
1255 .opaque_decl_anon = .pl_node,
1256 .opaque_decl_func = .pl_node,
1257 .error_set_decl = .pl_node,
1258 .error_set_decl_anon = .pl_node,
1259 .error_set_decl_func = .pl_node,
1260 .dbg_stmt = .dbg_stmt,
1261 .decl_ref = .str_tok,
1262 .decl_val = .str_tok,
1263 .load = .un_node,
1264 .div = .pl_node,
1265 .elem_ptr = .bin,
1266 .elem_ptr_node = .pl_node,
1267 .elem_val = .bin,
1268 .elem_val_node = .pl_node,
1269 .ensure_result_used = .un_node,
1270 .ensure_result_non_error = .un_node,
1271 .error_union_type = .pl_node,
1272 .error_value = .str_tok,
1273 .@"export" = .pl_node,
1274 .field_ptr = .pl_node,
1275 .field_val = .pl_node,
1276 .field_ptr_named = .pl_node,
1277 .field_val_named = .pl_node,
1278 .func = .pl_node,
1279 .func_inferred = .pl_node,
1280 .import = .str_tok,
1281 .int = .int,
1282 .int_big = .str,
1283 .float = .float,
1284 .float128 = .pl_node,
1285 .int_type = .int_type,
1286 .is_non_null = .un_node,
1287 .is_null = .un_node,
1288 .is_non_null_ptr = .un_node,
1289 .is_null_ptr = .un_node,
1290 .is_err = .un_node,
1291 .is_err_ptr = .un_node,
1292 .loop = .pl_node,
1293 .repeat = .node,
1294 .repeat_inline = .node,
1295 .merge_error_sets = .pl_node,
1296 .mod_rem = .pl_node,
1297 .mul = .pl_node,
1298 .mulwrap = .pl_node,
1299 .param_type = .param_type,
1300 .ref = .un_tok,
1301 .ret_node = .un_node,
1302 .ret_coerce = .un_tok,
1303 .ptr_type_simple = .ptr_type_simple,
1304 .ptr_type = .ptr_type,
1305 .slice_start = .pl_node,
1306 .slice_end = .pl_node,
1307 .slice_sentinel = .pl_node,
1308 .store = .bin,
1309 .store_node = .pl_node,
1310 .store_to_block_ptr = .bin,
1311 .store_to_inferred_ptr = .bin,
1312 .str = .str,
1313 .sub = .pl_node,
1314 .subwrap = .pl_node,
1315 .negate = .un_node,
1316 .negate_wrap = .un_node,
1317 .typeof = .un_node,
1318 .typeof_elem = .un_node,
1319 .typeof_log2_int_type = .un_node,
1320 .log2_int_type = .un_node,
1321 .@"unreachable" = .@"unreachable",
1322 .xor = .pl_node,
1323 .optional_type = .un_node,
1324 .optional_payload_safe = .un_node,
1325 .optional_payload_unsafe = .un_node,
1326 .optional_payload_safe_ptr = .un_node,
1327 .optional_payload_unsafe_ptr = .un_node,
1328 .err_union_payload_safe = .un_node,
1329 .err_union_payload_unsafe = .un_node,
1330 .err_union_payload_safe_ptr = .un_node,
1331 .err_union_payload_unsafe_ptr = .un_node,
1332 .err_union_code = .un_node,
1333 .err_union_code_ptr = .un_node,
1334 .ensure_err_payload_void = .un_tok,
1335 .enum_literal = .str_tok,
1336 .switch_block = .pl_node,
1337 .switch_block_multi = .pl_node,
1338 .switch_block_else = .pl_node,
1339 .switch_block_else_multi = .pl_node,
1340 .switch_block_under = .pl_node,
1341 .switch_block_under_multi = .pl_node,
1342 .switch_block_ref = .pl_node,
1343 .switch_block_ref_multi = .pl_node,
1344 .switch_block_ref_else = .pl_node,
1345 .switch_block_ref_else_multi = .pl_node,
1346 .switch_block_ref_under = .pl_node,
1347 .switch_block_ref_under_multi = .pl_node,
1348 .switch_capture = .switch_capture,
1349 .switch_capture_ref = .switch_capture,
1350 .switch_capture_multi = .switch_capture,
1351 .switch_capture_multi_ref = .switch_capture,
1352 .switch_capture_else = .switch_capture,
1353 .switch_capture_else_ref = .switch_capture,
1354 .validate_struct_init_ptr = .pl_node,
1355 .validate_array_init_ptr = .pl_node,
1356 .struct_init_empty = .un_node,
1357 .field_type = .pl_node,
1358 .field_type_ref = .pl_node,
1359 .struct_init = .pl_node,
1360 .struct_init_ref = .pl_node,
1361 .struct_init_anon = .pl_node,
1362 .struct_init_anon_ref = .pl_node,
1363 .array_init = .pl_node,
1364 .array_init_anon = .pl_node,
1365 .array_init_ref = .pl_node,
1366 .array_init_anon_ref = .pl_node,
1367 .union_init_ptr = .pl_node,
1368 .type_info = .un_node,
1369 .size_of = .un_node,
1370 .bit_size_of = .un_node,
1371 .fence = .node,
1372
1373 .ptr_to_int = .un_node,
1374 .error_to_int = .un_node,
1375 .int_to_error = .un_node,
1376 .compile_error = .un_node,
1377 .set_eval_branch_quota = .un_node,
1378 .enum_to_int = .un_node,
1379 .align_of = .un_node,
1380 .bool_to_int = .un_node,
1381 .embed_file = .un_node,
1382 .error_name = .un_node,
1383 .panic = .un_node,
1384 .set_align_stack = .un_node,
1385 .set_cold = .un_node,
1386 .set_float_mode = .un_node,
1387 .set_runtime_safety = .un_node,
1388 .sqrt = .un_node,
1389 .sin = .un_node,
1390 .cos = .un_node,
1391 .exp = .un_node,
1392 .exp2 = .un_node,
1393 .log = .un_node,
1394 .log2 = .un_node,
1395 .log10 = .un_node,
1396 .fabs = .un_node,
1397 .floor = .un_node,
1398 .ceil = .un_node,
1399 .trunc = .un_node,
1400 .round = .un_node,
1401 .tag_name = .un_node,
1402 .reify = .un_node,
1403 .type_name = .un_node,
1404 .frame_type = .un_node,
1405 .frame_size = .un_node,
1406
1407 .float_to_int = .pl_node,
1408 .int_to_float = .pl_node,
1409 .int_to_ptr = .pl_node,
1410 .int_to_enum = .pl_node,
1411 .float_cast = .pl_node,
1412 .int_cast = .pl_node,
1413 .err_set_cast = .pl_node,
1414 .ptr_cast = .pl_node,
1415 .truncate = .pl_node,
1416 .align_cast = .pl_node,
1417
1418 .has_decl = .pl_node,
1419 .has_field = .pl_node,
1420
1421 .clz = .un_node,
1422 .ctz = .un_node,
1423 .pop_count = .un_node,
1424 .byte_swap = .un_node,
1425 .bit_reverse = .un_node,
1426
1427 .div_exact = .pl_node,
1428 .div_floor = .pl_node,
1429 .div_trunc = .pl_node,
1430 .mod = .pl_node,
1431 .rem = .pl_node,
1432
1433 .shl = .pl_node,
1434 .shl_exact = .pl_node,
1435 .shr = .pl_node,
1436 .shr_exact = .pl_node,
1437
1438 .bit_offset_of = .pl_node,
1439 .byte_offset_of = .pl_node,
1440 .cmpxchg_strong = .pl_node,
1441 .cmpxchg_weak = .pl_node,
1442 .splat = .pl_node,
1443 .reduce = .pl_node,
1444 .shuffle = .pl_node,
1445 .atomic_load = .pl_node,
1446 .atomic_rmw = .pl_node,
1447 .atomic_store = .pl_node,
1448 .mul_add = .pl_node,
1449 .builtin_call = .pl_node,
1450 .field_ptr_type = .bin,
1451 .field_parent_ptr = .pl_node,
1452 .memcpy = .pl_node,
1453 .memset = .pl_node,
1454 .builtin_async_call = .pl_node,
1455 .c_import = .pl_node,
1456
1457 .alloc = .un_node,
1458 .alloc_mut = .un_node,
1459 .alloc_comptime = .un_node,
1460 .alloc_inferred = .node,
1461 .alloc_inferred_mut = .node,
1462 .alloc_inferred_comptime = .node,
1463 .resolve_inferred_alloc = .un_node,
1464
1465 .@"resume" = .un_node,
1466 .@"await" = .un_node,
1467 .await_nosuspend = .un_node,
1468
1469 .extended = .extended,
1470 });
1471 };
1472 };
1473
1474 /// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum.
1475 /// `noreturn` instructions may not go here; they must be part of the main `Tag` enum.
1476 pub const Extended = enum(u16) {
1477 /// Represents a function declaration or function prototype, depending on
1478 /// whether body_len is 0.
1479 /// `operand` is payload index to `ExtendedFunc`.
1480 /// `small` is `ExtendedFunc.Small`.
1481 func,
1482 /// Declares a global variable.
1483 /// `operand` is payload index to `ExtendedVar`.
1484 /// `small` is `ExtendedVar.Small`.
1485 variable,
1486 /// A struct type definition. Contains references to ZIR instructions for
1487 /// the field types, defaults, and alignments.
1488 /// `operand` is payload index to `StructDecl`.
1489 /// `small` is `StructDecl.Small`.
1490 struct_decl,
1491 /// An enum type definition. Contains references to ZIR instructions for
1492 /// the field value expressions and optional type tag expression.
1493 /// `operand` is payload index to `EnumDecl`.
1494 /// `small` is `EnumDecl.Small`.
1495 enum_decl,
1496 /// A union type definition. Contains references to ZIR instructions for
1497 /// the field types and optional type tag expression.
1498 /// `operand` is payload index to `UnionDecl`.
1499 /// `small` is `UnionDecl.Small`.
1500 union_decl,
1501 /// Obtains a pointer to the return value.
1502 /// `operand` is `src_node: i32`.
1503 ret_ptr,
1504 /// Obtains the return type of the in-scope function.
1505 /// `operand` is `src_node: i32`.
1506 ret_type,
1507 /// Implements the `@This` builtin.
1508 /// `operand` is `src_node: i32`.
1509 this,
1510 /// Implements the `@returnAddress` builtin.
1511 /// `operand` is `src_node: i32`.
1512 ret_addr,
1513 /// Implements the `@src` builtin.
1514 /// `operand` is `src_node: i32`.
1515 builtin_src,
1516 /// Implements the `@errorReturnTrace` builtin.
1517 /// `operand` is `src_node: i32`.
1518 error_return_trace,
1519 /// Implements the `@frame` builtin.
1520 /// `operand` is `src_node: i32`.
1521 frame,
1522 /// Implements the `@frameAddress` builtin.
1523 /// `operand` is `src_node: i32`.
1524 frame_address,
1525 /// Same as `alloc` from `Tag` but may contain an alignment instruction.
1526 /// `operand` is payload index to `AllocExtended`.
1527 /// `small`:
1528 /// * 0b000X - has type
1529 /// * 0b00X0 - has alignment
1530 /// * 0b0X00 - 1=const, 0=var
1531 /// * 0bX000 - is comptime
1532 alloc,
1533 /// The `@extern` builtin.
1534 /// `operand` is payload index to `BinNode`.
1535 builtin_extern,
1536 /// Inline assembly.
1537 /// `small`:
1538 /// * 0b00000000_000XXXXX - `outputs_len`.
1539 /// * 0b000000XX_XXX00000 - `inputs_len`.
1540 /// * 0b0XXXXX00_00000000 - `clobbers_len`.
1541 /// * 0bX0000000_00000000 - is volatile
1542 /// `operand` is payload index to `Asm`.
1543 @"asm",
1544 /// Log compile time variables and emit an error message.
1545 /// `operand` is payload index to `NodeMultiOp`.
1546 /// `small` is `operands_len`.
1547 /// The AST node is the compile log builtin call.
1548 compile_log,
1549 /// The builtin `@TypeOf` which returns the type after Peer Type Resolution
1550 /// of one or more params.
1551 /// `operand` is payload index to `NodeMultiOp`.
1552 /// `small` is `operands_len`.
1553 /// The AST node is the builtin call.
1554 typeof_peer,
1555 /// Implements the `@addWithOverflow` builtin.
1556 /// `operand` is payload index to `OverflowArithmetic`.
1557 /// `small` is unused.
1558 add_with_overflow,
1559 /// Implements the `@subWithOverflow` builtin.
1560 /// `operand` is payload index to `OverflowArithmetic`.
1561 /// `small` is unused.
1562 sub_with_overflow,
1563 /// Implements the `@mulWithOverflow` builtin.
1564 /// `operand` is payload index to `OverflowArithmetic`.
1565 /// `small` is unused.
1566 mul_with_overflow,
1567 /// Implements the `@shlWithOverflow` builtin.
1568 /// `operand` is payload index to `OverflowArithmetic`.
1569 /// `small` is unused.
1570 shl_with_overflow,
1571 /// `operand` is payload index to `UnNode`.
1572 c_undef,
1573 /// `operand` is payload index to `UnNode`.
1574 c_include,
1575 /// `operand` is payload index to `BinNode`.
1576 c_define,
1577 /// `operand` is payload index to `UnNode`.
1578 wasm_memory_size,
1579 /// `operand` is payload index to `BinNode`.
1580 wasm_memory_grow,
1581
1582 pub const InstData = struct {
1583 opcode: Extended,
1584 small: u16,
1585 operand: u32,
1586 };
1587 };
1588
1589 /// The position of a ZIR instruction within the `Zir` instructions array.
1590 pub const Index = u32;
1591
1592 /// A reference to a TypedValue or ZIR instruction.
1593 ///
1594 /// If the Ref has a tag in this enum, it refers to a TypedValue which may be
1595 /// retrieved with Ref.toTypedValue().
1596 ///
1597 /// If the value of a Ref does not have a tag, it refers to a ZIR instruction.
1598 ///
1599 /// The first values after the the last tag refer to ZIR instructions which may
1600 /// be derived by subtracting `typed_value_map.len`.
1601 ///
1602 /// When adding a tag to this enum, consider adding a corresponding entry to
1603 /// `simple_types` in astgen.
1604 ///
1605 /// The tag type is specified so that it is safe to bitcast between `[]u32`
1606 /// and `[]Ref`.
1607 pub const Ref = enum(u32) {
1608 /// This Ref does not correspond to any ZIR instruction or constant
1609 /// value and may instead be used as a sentinel to indicate null.
1610 none,
1611
1612 u8_type,
1613 i8_type,
1614 u16_type,
1615 i16_type,
1616 u32_type,
1617 i32_type,
1618 u64_type,
1619 i64_type,
1620 u128_type,
1621 i128_type,
1622 usize_type,
1623 isize_type,
1624 c_short_type,
1625 c_ushort_type,
1626 c_int_type,
1627 c_uint_type,
1628 c_long_type,
1629 c_ulong_type,
1630 c_longlong_type,
1631 c_ulonglong_type,
1632 c_longdouble_type,
1633 f16_type,
1634 f32_type,
1635 f64_type,
1636 f128_type,
1637 c_void_type,
1638 bool_type,
1639 void_type,
1640 type_type,
1641 anyerror_type,
1642 comptime_int_type,
1643 comptime_float_type,
1644 noreturn_type,
1645 anyframe_type,
1646 null_type,
1647 undefined_type,
1648 enum_literal_type,
1649 atomic_ordering_type,
1650 atomic_rmw_op_type,
1651 calling_convention_type,
1652 float_mode_type,
1653 reduce_op_type,
1654 call_options_type,
1655 export_options_type,
1656 extern_options_type,
1657 manyptr_u8_type,
1658 manyptr_const_u8_type,
1659 fn_noreturn_no_args_type,
1660 fn_void_no_args_type,
1661 fn_naked_noreturn_no_args_type,
1662 fn_ccc_void_no_args_type,
1663 single_const_pointer_to_comptime_int_type,
1664 const_slice_u8_type,
1665
1666 /// `undefined` (untyped)
1667 undef,
1668 /// `0` (comptime_int)
1669 zero,
1670 /// `1` (comptime_int)
1671 one,
1672 /// `{}`
1673 void_value,
1674 /// `unreachable` (noreturn type)
1675 unreachable_value,
1676 /// `null` (untyped)
1677 null_value,
1678 /// `true`
1679 bool_true,
1680 /// `false`
1681 bool_false,
1682 /// `.{}` (untyped)
1683 empty_struct,
1684 /// `0` (usize)
1685 zero_usize,
1686 /// `1` (usize)
1687 one_usize,
1688 /// `std.builtin.CallingConvention.C`
1689 calling_convention_c,
1690
1691 _,
1692
1693 pub const typed_value_map = std.enums.directEnumArray(Ref, TypedValue, 0, .{
1694 .none = undefined,
1695
1696 .u8_type = .{
1697 .ty = Type.initTag(.type),
1698 .val = Value.initTag(.u8_type),
1699 },
1700 .i8_type = .{
1701 .ty = Type.initTag(.type),
1702 .val = Value.initTag(.i8_type),
1703 },
1704 .u16_type = .{
1705 .ty = Type.initTag(.type),
1706 .val = Value.initTag(.u16_type),
1707 },
1708 .i16_type = .{
1709 .ty = Type.initTag(.type),
1710 .val = Value.initTag(.i16_type),
1711 },
1712 .u32_type = .{
1713 .ty = Type.initTag(.type),
1714 .val = Value.initTag(.u32_type),
1715 },
1716 .i32_type = .{
1717 .ty = Type.initTag(.type),
1718 .val = Value.initTag(.i32_type),
1719 },
1720 .u64_type = .{
1721 .ty = Type.initTag(.type),
1722 .val = Value.initTag(.u64_type),
1723 },
1724 .i64_type = .{
1725 .ty = Type.initTag(.type),
1726 .val = Value.initTag(.i64_type),
1727 },
1728 .u128_type = .{
1729 .ty = Type.initTag(.type),
1730 .val = Value.initTag(.u128_type),
1731 },
1732 .i128_type = .{
1733 .ty = Type.initTag(.type),
1734 .val = Value.initTag(.i128_type),
1735 },
1736 .usize_type = .{
1737 .ty = Type.initTag(.type),
1738 .val = Value.initTag(.usize_type),
1739 },
1740 .isize_type = .{
1741 .ty = Type.initTag(.type),
1742 .val = Value.initTag(.isize_type),
1743 },
1744 .c_short_type = .{
1745 .ty = Type.initTag(.type),
1746 .val = Value.initTag(.c_short_type),
1747 },
1748 .c_ushort_type = .{
1749 .ty = Type.initTag(.type),
1750 .val = Value.initTag(.c_ushort_type),
1751 },
1752 .c_int_type = .{
1753 .ty = Type.initTag(.type),
1754 .val = Value.initTag(.c_int_type),
1755 },
1756 .c_uint_type = .{
1757 .ty = Type.initTag(.type),
1758 .val = Value.initTag(.c_uint_type),
1759 },
1760 .c_long_type = .{
1761 .ty = Type.initTag(.type),
1762 .val = Value.initTag(.c_long_type),
1763 },
1764 .c_ulong_type = .{
1765 .ty = Type.initTag(.type),
1766 .val = Value.initTag(.c_ulong_type),
1767 },
1768 .c_longlong_type = .{
1769 .ty = Type.initTag(.type),
1770 .val = Value.initTag(.c_longlong_type),
1771 },
1772 .c_ulonglong_type = .{
1773 .ty = Type.initTag(.type),
1774 .val = Value.initTag(.c_ulonglong_type),
1775 },
1776 .c_longdouble_type = .{
1777 .ty = Type.initTag(.type),
1778 .val = Value.initTag(.c_longdouble_type),
1779 },
1780 .f16_type = .{
1781 .ty = Type.initTag(.type),
1782 .val = Value.initTag(.f16_type),
1783 },
1784 .f32_type = .{
1785 .ty = Type.initTag(.type),
1786 .val = Value.initTag(.f32_type),
1787 },
1788 .f64_type = .{
1789 .ty = Type.initTag(.type),
1790 .val = Value.initTag(.f64_type),
1791 },
1792 .f128_type = .{
1793 .ty = Type.initTag(.type),
1794 .val = Value.initTag(.f128_type),
1795 },
1796 .c_void_type = .{
1797 .ty = Type.initTag(.type),
1798 .val = Value.initTag(.c_void_type),
1799 },
1800 .bool_type = .{
1801 .ty = Type.initTag(.type),
1802 .val = Value.initTag(.bool_type),
1803 },
1804 .void_type = .{
1805 .ty = Type.initTag(.type),
1806 .val = Value.initTag(.void_type),
1807 },
1808 .type_type = .{
1809 .ty = Type.initTag(.type),
1810 .val = Value.initTag(.type_type),
1811 },
1812 .anyerror_type = .{
1813 .ty = Type.initTag(.type),
1814 .val = Value.initTag(.anyerror_type),
1815 },
1816 .comptime_int_type = .{
1817 .ty = Type.initTag(.type),
1818 .val = Value.initTag(.comptime_int_type),
1819 },
1820 .comptime_float_type = .{
1821 .ty = Type.initTag(.type),
1822 .val = Value.initTag(.comptime_float_type),
1823 },
1824 .noreturn_type = .{
1825 .ty = Type.initTag(.type),
1826 .val = Value.initTag(.noreturn_type),
1827 },
1828 .anyframe_type = .{
1829 .ty = Type.initTag(.type),
1830 .val = Value.initTag(.anyframe_type),
1831 },
1832 .null_type = .{
1833 .ty = Type.initTag(.type),
1834 .val = Value.initTag(.null_type),
1835 },
1836 .undefined_type = .{
1837 .ty = Type.initTag(.type),
1838 .val = Value.initTag(.undefined_type),
1839 },
1840 .fn_noreturn_no_args_type = .{
1841 .ty = Type.initTag(.type),
1842 .val = Value.initTag(.fn_noreturn_no_args_type),
1843 },
1844 .fn_void_no_args_type = .{
1845 .ty = Type.initTag(.type),
1846 .val = Value.initTag(.fn_void_no_args_type),
1847 },
1848 .fn_naked_noreturn_no_args_type = .{
1849 .ty = Type.initTag(.type),
1850 .val = Value.initTag(.fn_naked_noreturn_no_args_type),
1851 },
1852 .fn_ccc_void_no_args_type = .{
1853 .ty = Type.initTag(.type),
1854 .val = Value.initTag(.fn_ccc_void_no_args_type),
1855 },
1856 .single_const_pointer_to_comptime_int_type = .{
1857 .ty = Type.initTag(.type),
1858 .val = Value.initTag(.single_const_pointer_to_comptime_int_type),
1859 },
1860 .const_slice_u8_type = .{
1861 .ty = Type.initTag(.type),
1862 .val = Value.initTag(.const_slice_u8_type),
1863 },
1864 .enum_literal_type = .{
1865 .ty = Type.initTag(.type),
1866 .val = Value.initTag(.enum_literal_type),
1867 },
1868 .manyptr_u8_type = .{
1869 .ty = Type.initTag(.type),
1870 .val = Value.initTag(.manyptr_u8_type),
1871 },
1872 .manyptr_const_u8_type = .{
1873 .ty = Type.initTag(.type),
1874 .val = Value.initTag(.manyptr_const_u8_type),
1875 },
1876 .atomic_ordering_type = .{
1877 .ty = Type.initTag(.type),
1878 .val = Value.initTag(.atomic_ordering_type),
1879 },
1880 .atomic_rmw_op_type = .{
1881 .ty = Type.initTag(.type),
1882 .val = Value.initTag(.atomic_rmw_op_type),
1883 },
1884 .calling_convention_type = .{
1885 .ty = Type.initTag(.type),
1886 .val = Value.initTag(.calling_convention_type),
1887 },
1888 .float_mode_type = .{
1889 .ty = Type.initTag(.type),
1890 .val = Value.initTag(.float_mode_type),
1891 },
1892 .reduce_op_type = .{
1893 .ty = Type.initTag(.type),
1894 .val = Value.initTag(.reduce_op_type),
1895 },
1896 .call_options_type = .{
1897 .ty = Type.initTag(.type),
1898 .val = Value.initTag(.call_options_type),
1899 },
1900 .export_options_type = .{
1901 .ty = Type.initTag(.type),
1902 .val = Value.initTag(.export_options_type),
1903 },
1904 .extern_options_type = .{
1905 .ty = Type.initTag(.type),
1906 .val = Value.initTag(.extern_options_type),
1907 },
1908
1909 .undef = .{
1910 .ty = Type.initTag(.@"undefined"),
1911 .val = Value.initTag(.undef),
1912 },
1913 .zero = .{
1914 .ty = Type.initTag(.comptime_int),
1915 .val = Value.initTag(.zero),
1916 },
1917 .zero_usize = .{
1918 .ty = Type.initTag(.usize),
1919 .val = Value.initTag(.zero),
1920 },
1921 .one = .{
1922 .ty = Type.initTag(.comptime_int),
1923 .val = Value.initTag(.one),
1924 },
1925 .one_usize = .{
1926 .ty = Type.initTag(.usize),
1927 .val = Value.initTag(.one),
1928 },
1929 .void_value = .{
1930 .ty = Type.initTag(.void),
1931 .val = Value.initTag(.void_value),
1932 },
1933 .unreachable_value = .{
1934 .ty = Type.initTag(.noreturn),
1935 .val = Value.initTag(.unreachable_value),
1936 },
1937 .null_value = .{
1938 .ty = Type.initTag(.@"null"),
1939 .val = Value.initTag(.null_value),
1940 },
1941 .bool_true = .{
1942 .ty = Type.initTag(.bool),
1943 .val = Value.initTag(.bool_true),
1944 },
1945 .bool_false = .{
1946 .ty = Type.initTag(.bool),
1947 .val = Value.initTag(.bool_false),
1948 },
1949 .empty_struct = .{
1950 .ty = Type.initTag(.empty_struct_literal),
1951 .val = Value.initTag(.empty_struct_value),
1952 },
1953 .calling_convention_c = .{
1954 .ty = Type.initTag(.calling_convention),
1955 .val = .{ .ptr_otherwise = &calling_convention_c_payload.base },
1956 },
1957 });
1958 };
1959
1960 /// We would like this to be const but `Value` wants a mutable pointer for
1961 /// its payload field. Nothing should mutate this though.
1962 var calling_convention_c_payload: Value.Payload.U32 = .{
1963 .base = .{ .tag = .enum_field_index },
1964 .data = @enumToInt(std.builtin.CallingConvention.C),
1965 };
1966
1967 /// All instructions have an 8-byte payload, which is contained within
1968 /// this union. `Tag` determines which union field is active, as well as
1969 /// how to interpret the data within.
1970 pub const Data = union {
1971 /// Used for `Tag.extended`. The extended opcode determines the meaning
1972 /// of the `small` and `operand` fields.
1973 extended: Extended.InstData,
1974 /// Used for unary operators, with an AST node source location.
1975 un_node: struct {
1976 /// Offset from Decl AST node index.
1977 src_node: i32,
1978 /// The meaning of this operand depends on the corresponding `Tag`.
1979 operand: Ref,
1980
1981 pub fn src(self: @This()) LazySrcLoc {
1982 return .{ .node_offset = self.src_node };
1983 }
1984 },
1985 /// Used for unary operators, with a token source location.
1986 un_tok: struct {
1987 /// Offset from Decl AST token index.
1988 src_tok: ast.TokenIndex,
1989 /// The meaning of this operand depends on the corresponding `Tag`.
1990 operand: Ref,
1991
1992 pub fn src(self: @This()) LazySrcLoc {
1993 return .{ .token_offset = self.src_tok };
1994 }
1995 },
1996 pl_node: struct {
1997 /// Offset from Decl AST node index.
1998 /// `Tag` determines which kind of AST node this points to.
1999 src_node: i32,
2000 /// index into extra.
2001 /// `Tag` determines what lives there.
2002 payload_index: u32,
2003
2004 pub fn src(self: @This()) LazySrcLoc {
2005 return .{ .node_offset = self.src_node };
2006 }
2007 },
2008 bin: Bin,
2009 /// For strings which may contain null bytes.
2010 str: struct {
2011 /// Offset into `string_bytes`.
2012 start: u32,
2013 /// Number of bytes in the string.
2014 len: u32,
2015
2016 pub fn get(self: @This(), code: Zir) []const u8 {
2017 return code.string_bytes[self.start..][0..self.len];
2018 }
2019 },
2020 str_tok: struct {
2021 /// Offset into `string_bytes`. Null-terminated.
2022 start: u32,
2023 /// Offset from Decl AST token index.
2024 src_tok: u32,
2025
2026 pub fn get(self: @This(), code: Zir) [:0]const u8 {
2027 return code.nullTerminatedString(self.start);
2028 }
2029
2030 pub fn src(self: @This()) LazySrcLoc {
2031 return .{ .token_offset = self.src_tok };
2032 }
2033 },
2034 /// Offset from Decl AST token index.
2035 tok: ast.TokenIndex,
2036 /// Offset from Decl AST node index.
2037 node: i32,
2038 int: u64,
2039 float: struct {
2040 /// Offset from Decl AST node index.
2041 /// `Tag` determines which kind of AST node this points to.
2042 src_node: i32,
2043 number: f32,
2044
2045 pub fn src(self: @This()) LazySrcLoc {
2046 return .{ .node_offset = self.src_node };
2047 }
2048 },
2049 array_type_sentinel: struct {
2050 len: Ref,
2051 /// index into extra, points to an `ArrayTypeSentinel`
2052 payload_index: u32,
2053 },
2054 ptr_type_simple: struct {
2055 is_allowzero: bool,
2056 is_mutable: bool,
2057 is_volatile: bool,
2058 size: std.builtin.TypeInfo.Pointer.Size,
2059 elem_type: Ref,
2060 },
2061 ptr_type: struct {
2062 flags: packed struct {
2063 is_allowzero: bool,
2064 is_mutable: bool,
2065 is_volatile: bool,
2066 has_sentinel: bool,
2067 has_align: bool,
2068 has_bit_range: bool,
2069 _: u2 = undefined,
2070 },
2071 size: std.builtin.TypeInfo.Pointer.Size,
2072 /// Index into extra. See `PtrType`.
2073 payload_index: u32,
2074 },
2075 int_type: struct {
2076 /// Offset from Decl AST node index.
2077 /// `Tag` determines which kind of AST node this points to.
2078 src_node: i32,
2079 signedness: std.builtin.Signedness,
2080 bit_count: u16,
2081
2082 pub fn src(self: @This()) LazySrcLoc {
2083 return .{ .node_offset = self.src_node };
2084 }
2085 },
2086 bool_br: struct {
2087 lhs: Ref,
2088 /// Points to a `Block`.
2089 payload_index: u32,
2090 },
2091 param_type: struct {
2092 callee: Ref,
2093 param_index: u32,
2094 },
2095 @"unreachable": struct {
2096 /// Offset from Decl AST node index.
2097 /// `Tag` determines which kind of AST node this points to.
2098 src_node: i32,
2099 /// `false`: Not safety checked - the compiler will assume the
2100 /// correctness of this instruction.
2101 /// `true`: In safety-checked modes, this will generate a call
2102 /// to the panic function unless it can be proven unreachable by the compiler.
2103 safety: bool,
2104
2105 pub fn src(self: @This()) LazySrcLoc {
2106 return .{ .node_offset = self.src_node };
2107 }
2108 },
2109 @"break": struct {
2110 block_inst: Index,
2111 operand: Ref,
2112 },
2113 switch_capture: struct {
2114 switch_inst: Index,
2115 prong_index: u32,
2116 },
2117 dbg_stmt: struct {
2118 line: u32,
2119 column: u32,
2120 },
2121
2122 // Make sure we don't accidentally add a field to make this union
2123 // bigger than expected. Note that in Debug builds, Zig is allowed
2124 // to insert a secret field for safety checks.
2125 comptime {
2126 if (std.builtin.mode != .Debug) {
2127 assert(@sizeOf(Data) == 8);
2128 }
2129 }
2130
2131 /// TODO this has to be kept in sync with `Data` which we want to be an untagged
2132 /// union. There is some kind of language awkwardness here and it has to do with
2133 /// deserializing an untagged union (in this case `Data`) from a file, and trying
2134 /// to preserve the hidden safety field.
2135 pub const FieldEnum = enum {
2136 extended,
2137 un_node,
2138 un_tok,
2139 pl_node,
2140 bin,
2141 str,
2142 str_tok,
2143 tok,
2144 node,
2145 int,
2146 float,
2147 array_type_sentinel,
2148 ptr_type_simple,
2149 ptr_type,
2150 int_type,
2151 bool_br,
2152 param_type,
2153 @"unreachable",
2154 @"break",
2155 switch_capture,
2156 dbg_stmt,
2157 };
2158 };
2159
2160 /// Trailing:
2161 /// 0. Output for every outputs_len
2162 /// 1. Input for every inputs_len
2163 /// 2. clobber: u32 // index into string_bytes (null terminated) for every clobbers_len.
2164 pub const Asm = struct {
2165 src_node: i32,
2166 asm_source: Ref,
2167 /// 1 bit for each outputs_len: whether it uses `-> T` or not.
2168 /// 0b0 - operand is a pointer to where to store the output.
2169 /// 0b1 - operand is a type; asm expression has the output as the result.
2170 /// 0b0X is the first output, 0bX0 is the second, etc.
2171 output_type_bits: u32,
2172
2173 pub const Output = struct {
2174 /// index into string_bytes (null terminated)
2175 name: u32,
2176 /// index into string_bytes (null terminated)
2177 constraint: u32,
2178 /// How to interpret this is determined by `output_type_bits`.
2179 operand: Ref,
2180 };
2181
2182 pub const Input = struct {
2183 /// index into string_bytes (null terminated)
2184 name: u32,
2185 /// index into string_bytes (null terminated)
2186 constraint: u32,
2187 operand: Ref,
2188 };
2189 };
2190
2191 /// Trailing:
2192 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
2193 /// 1. cc: Ref, // if has_cc is set
2194 /// 2. align: Ref, // if has_align is set
2195 /// 3. param_type: Ref // for each param_types_len
2196 /// 4. body: Index // for each body_len
2197 /// 5. src_locs: Func.SrcLocs // if body_len != 0
2198 pub const ExtendedFunc = struct {
2199 src_node: i32,
2200 return_type: Ref,
2201 param_types_len: u32,
2202 body_len: u32,
2203
2204 pub const Small = packed struct {
2205 is_var_args: bool,
2206 is_inferred_error: bool,
2207 has_lib_name: bool,
2208 has_cc: bool,
2209 has_align: bool,
2210 is_test: bool,
2211 is_extern: bool,
2212 _: u9 = undefined,
2213 };
2214 };
2215
2216 /// Trailing:
2217 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
2218 /// 1. align: Ref, // if has_align is set
2219 /// 2. init: Ref // if has_init is set
2220 /// The source node is obtained from the containing `block_inline`.
2221 pub const ExtendedVar = struct {
2222 var_type: Ref,
2223
2224 pub const Small = packed struct {
2225 has_lib_name: bool,
2226 has_align: bool,
2227 has_init: bool,
2228 is_extern: bool,
2229 is_threadlocal: bool,
2230 _: u11 = undefined,
2231 };
2232 };
2233
2234 /// Trailing:
2235 /// 0. param_type: Ref // for each param_types_len
2236 /// - `none` indicates that the param type is `anytype`.
2237 /// 1. body: Index // for each body_len
2238 /// 2. src_locs: SrcLocs // if body_len != 0
2239 pub const Func = struct {
2240 return_type: Ref,
2241 param_types_len: u32,
2242 body_len: u32,
2243
2244 pub const SrcLocs = struct {
2245 /// Absolute line index in the source file.
2246 lbrace_line: u32,
2247 /// Absolute line index in the source file.
2248 rbrace_line: u32,
2249 /// lbrace_column is least significant bits u16
2250 /// rbrace_column is most significant bits u16
2251 columns: u32,
2252 };
2253 };
2254
2255 /// This data is stored inside extra, with trailing operands according to `operands_len`.
2256 /// Each operand is a `Ref`.
2257 pub const MultiOp = struct {
2258 operands_len: u32,
2259 };
2260
2261 /// Trailing: operand: Ref, // for each `operands_len` (stored in `small`).
2262 pub const NodeMultiOp = struct {
2263 src_node: i32,
2264 };
2265
2266 /// This data is stored inside extra, with trailing operands according to `body_len`.
2267 /// Each operand is an `Index`.
2268 pub const Block = struct {
2269 body_len: u32,
2270 };
2271
2272 /// Stored inside extra, with trailing arguments according to `args_len`.
2273 /// Each argument is a `Ref`.
2274 pub const Call = struct {
2275 callee: Ref,
2276 args_len: u32,
2277 };
2278
2279 pub const BuiltinCall = struct {
2280 options: Ref,
2281 callee: Ref,
2282 args: Ref,
2283 };
2284
2285 /// This data is stored inside extra, with two sets of trailing `Ref`:
2286 /// * 0. the then body, according to `then_body_len`.
2287 /// * 1. the else body, according to `else_body_len`.
2288 pub const CondBr = struct {
2289 condition: Ref,
2290 then_body_len: u32,
2291 else_body_len: u32,
2292 };
2293
2294 /// Stored in extra. Depending on the flags in Data, there will be up to 4
2295 /// trailing Ref fields:
2296 /// 0. sentinel: Ref // if `has_sentinel` flag is set
2297 /// 1. align: Ref // if `has_align` flag is set
2298 /// 2. bit_start: Ref // if `has_bit_range` flag is set
2299 /// 3. bit_end: Ref // if `has_bit_range` flag is set
2300 pub const PtrType = struct {
2301 elem_type: Ref,
2302 };
2303
2304 pub const ArrayTypeSentinel = struct {
2305 sentinel: Ref,
2306 elem_type: Ref,
2307 };
2308
2309 pub const SliceStart = struct {
2310 lhs: Ref,
2311 start: Ref,
2312 };
2313
2314 pub const SliceEnd = struct {
2315 lhs: Ref,
2316 start: Ref,
2317 end: Ref,
2318 };
2319
2320 pub const SliceSentinel = struct {
2321 lhs: Ref,
2322 start: Ref,
2323 end: Ref,
2324 sentinel: Ref,
2325 };
2326
2327 /// The meaning of these operands depends on the corresponding `Tag`.
2328 pub const Bin = struct {
2329 lhs: Ref,
2330 rhs: Ref,
2331 };
2332
2333 pub const BinNode = struct {
2334 node: i32,
2335 lhs: Ref,
2336 rhs: Ref,
2337 };
2338
2339 pub const UnNode = struct {
2340 node: i32,
2341 operand: Ref,
2342 };
2343
2344 /// This form is supported when there are no ranges, and exactly 1 item per block.
2345 /// Depending on zir tag and len fields, extra fields trail
2346 /// this one in the extra array.
2347 /// 0. else_body { // If the tag has "_else" or "_under" in it.
2348 /// body_len: u32,
2349 /// body member Index for every body_len
2350 /// }
2351 /// 1. cases: {
2352 /// item: Ref,
2353 /// body_len: u32,
2354 /// body member Index for every body_len
2355 /// } for every cases_len
2356 pub const SwitchBlock = struct {
2357 operand: Ref,
2358 cases_len: u32,
2359 };
2360
2361 /// This form is required when there exists a block which has more than one item,
2362 /// or a range.
2363 /// Depending on zir tag and len fields, extra fields trail
2364 /// this one in the extra array.
2365 /// 0. else_body { // If the tag has "_else" or "_under" in it.
2366 /// body_len: u32,
2367 /// body member Index for every body_len
2368 /// }
2369 /// 1. scalar_cases: { // for every scalar_cases_len
2370 /// item: Ref,
2371 /// body_len: u32,
2372 /// body member Index for every body_len
2373 /// }
2374 /// 2. multi_cases: { // for every multi_cases_len
2375 /// items_len: u32,
2376 /// ranges_len: u32,
2377 /// body_len: u32,
2378 /// item: Ref // for every items_len
2379 /// ranges: { // for every ranges_len
2380 /// item_first: Ref,
2381 /// item_last: Ref,
2382 /// }
2383 /// body member Index for every body_len
2384 /// }
2385 pub const SwitchBlockMulti = struct {
2386 operand: Ref,
2387 scalar_cases_len: u32,
2388 multi_cases_len: u32,
2389 };
2390
2391 pub const Field = struct {
2392 lhs: Ref,
2393 /// Offset into `string_bytes`.
2394 field_name_start: u32,
2395 };
2396
2397 pub const FieldNamed = struct {
2398 lhs: Ref,
2399 field_name: Ref,
2400 };
2401
2402 pub const As = struct {
2403 dest_type: Ref,
2404 operand: Ref,
2405 };
2406
2407 /// Trailing:
2408 /// 0. src_node: i32, // if has_src_node
2409 /// 1. body_len: u32, // if has_body_len
2410 /// 2. fields_len: u32, // if has_fields_len
2411 /// 3. decls_len: u32, // if has_decls_len
2412 /// 4. decl_bits: u32 // for every 8 decls
2413 /// - sets of 4 bits:
2414 /// 0b000X: whether corresponding decl is pub
2415 /// 0b00X0: whether corresponding decl is exported
2416 /// 0b0X00: whether corresponding decl has an align expression
2417 /// 0bX000: whether corresponding decl has a linksection expression
2418 /// 5. decl: { // for every decls_len
2419 /// src_hash: [4]u32, // hash of source bytes
2420 /// line: u32, // line number of decl, relative to parent
2421 /// name: u32, // null terminated string index
2422 /// - 0 means comptime or usingnamespace decl.
2423 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2424 /// - 1 means test decl with no name.
2425 /// - if there is a 0 byte at the position `name` indexes, it indicates
2426 /// this is a test decl, and the name starts at `name+1`.
2427 /// value: Index,
2428 /// align: Ref, // if corresponding bit is set
2429 /// link_section: Ref, // if corresponding bit is set
2430 /// }
2431 /// 6. inst: Index // for every body_len
2432 /// 7. flags: u32 // for every 8 fields
2433 /// - sets of 4 bits:
2434 /// 0b000X: whether corresponding field has an align expression
2435 /// 0b00X0: whether corresponding field has a default expression
2436 /// 0b0X00: whether corresponding field is comptime
2437 /// 0bX000: unused
2438 /// 8. fields: { // for every fields_len
2439 /// field_name: u32,
2440 /// field_type: Ref,
2441 /// - if none, means `anytype`.
2442 /// align: Ref, // if corresponding bit is set
2443 /// default_value: Ref, // if corresponding bit is set
2444 /// }
2445 pub const StructDecl = struct {
2446 pub const Small = packed struct {
2447 has_src_node: bool,
2448 has_body_len: bool,
2449 has_fields_len: bool,
2450 has_decls_len: bool,
2451 name_strategy: NameStrategy,
2452 layout: std.builtin.TypeInfo.ContainerLayout,
2453 _: u8 = undefined,
2454 };
2455 };
2456
2457 pub const NameStrategy = enum(u2) {
2458 /// Use the same name as the parent declaration name.
2459 /// e.g. `const Foo = struct {...};`.
2460 parent,
2461 /// Use the name of the currently executing comptime function call,
2462 /// with the current parameters. e.g. `ArrayList(i32)`.
2463 func,
2464 /// Create an anonymous name for this declaration.
2465 /// Like this: "ParentDeclName_struct_69"
2466 anon,
2467 };
2468
2469 /// Trailing:
2470 /// 0. src_node: i32, // if has_src_node
2471 /// 1. tag_type: Ref, // if has_tag_type
2472 /// 2. body_len: u32, // if has_body_len
2473 /// 3. fields_len: u32, // if has_fields_len
2474 /// 4. decls_len: u32, // if has_decls_len
2475 /// 5. decl_bits: u32 // for every 8 decls
2476 /// - sets of 4 bits:
2477 /// 0b000X: whether corresponding decl is pub
2478 /// 0b00X0: whether corresponding decl is exported
2479 /// 0b0X00: whether corresponding decl has an align expression
2480 /// 0bX000: whether corresponding decl has a linksection expression
2481 /// 6. decl: { // for every decls_len
2482 /// src_hash: [4]u32, // hash of source bytes
2483 /// line: u32, // line number of decl, relative to parent
2484 /// name: u32, // null terminated string index
2485 /// - 0 means comptime or usingnamespace decl.
2486 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2487 /// - 1 means test decl with no name.
2488 /// - if there is a 0 byte at the position `name` indexes, it indicates
2489 /// this is a test decl, and the name starts at `name+1`.
2490 /// value: Index,
2491 /// align: Ref, // if corresponding bit is set
2492 /// link_section: Ref, // if corresponding bit is set
2493 /// }
2494 /// 7. inst: Index // for every body_len
2495 /// 8. has_bits: u32 // for every 32 fields
2496 /// - the bit is whether corresponding field has an value expression
2497 /// 9. fields: { // for every fields_len
2498 /// field_name: u32,
2499 /// value: Ref, // if corresponding bit is set
2500 /// }
2501 pub const EnumDecl = struct {
2502 pub const Small = packed struct {
2503 has_src_node: bool,
2504 has_tag_type: bool,
2505 has_body_len: bool,
2506 has_fields_len: bool,
2507 has_decls_len: bool,
2508 name_strategy: NameStrategy,
2509 nonexhaustive: bool,
2510 _: u8 = undefined,
2511 };
2512 };
2513
2514 /// Trailing:
2515 /// 0. src_node: i32, // if has_src_node
2516 /// 1. tag_type: Ref, // if has_tag_type
2517 /// 2. body_len: u32, // if has_body_len
2518 /// 3. fields_len: u32, // if has_fields_len
2519 /// 4. decls_len: u32, // if has_decls_len
2520 /// 5. decl_bits: u32 // for every 8 decls
2521 /// - sets of 4 bits:
2522 /// 0b000X: whether corresponding decl is pub
2523 /// 0b00X0: whether corresponding decl is exported
2524 /// 0b0X00: whether corresponding decl has an align expression
2525 /// 0bX000: whether corresponding decl has a linksection expression
2526 /// 6. decl: { // for every decls_len
2527 /// src_hash: [4]u32, // hash of source bytes
2528 /// line: u32, // line number of decl, relative to parent
2529 /// name: u32, // null terminated string index
2530 /// - 0 means comptime or usingnamespace decl.
2531 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2532 /// - 1 means test decl with no name.
2533 /// - if there is a 0 byte at the position `name` indexes, it indicates
2534 /// this is a test decl, and the name starts at `name+1`.
2535 /// value: Index,
2536 /// align: Ref, // if corresponding bit is set
2537 /// link_section: Ref, // if corresponding bit is set
2538 /// }
2539 /// 7. inst: Index // for every body_len
2540 /// 8. has_bits: u32 // for every 8 fields
2541 /// - sets of 4 bits:
2542 /// 0b000X: whether corresponding field has a type expression
2543 /// 0b00X0: whether corresponding field has a align expression
2544 /// 0b0X00: whether corresponding field has a tag value expression
2545 /// 0bX000: unused
2546 /// 9. fields: { // for every fields_len
2547 /// field_name: u32, // null terminated string index
2548 /// field_type: Ref, // if corresponding bit is set
2549 /// align: Ref, // if corresponding bit is set
2550 /// tag_value: Ref, // if corresponding bit is set
2551 /// }
2552 pub const UnionDecl = struct {
2553 pub const Small = packed struct {
2554 has_src_node: bool,
2555 has_tag_type: bool,
2556 has_body_len: bool,
2557 has_fields_len: bool,
2558 has_decls_len: bool,
2559 name_strategy: NameStrategy,
2560 layout: std.builtin.TypeInfo.ContainerLayout,
2561 /// false: union(tag_type)
2562 /// true: union(enum(tag_type))
2563 auto_enum_tag: bool,
2564 _: u6 = undefined,
2565 };
2566 };
2567
2568 /// Trailing:
2569 /// 0. decl_bits: u32 // for every 8 decls
2570 /// - sets of 4 bits:
2571 /// 0b000X: whether corresponding decl is pub
2572 /// 0b00X0: whether corresponding decl is exported
2573 /// 0b0X00: whether corresponding decl has an align expression
2574 /// 0bX000: whether corresponding decl has a linksection expression
2575 /// 1. decl: { // for every decls_len
2576 /// src_hash: [4]u32, // hash of source bytes
2577 /// line: u32, // line number of decl, relative to parent
2578 /// name: u32, // null terminated string index
2579 /// - 0 means comptime or usingnamespace decl.
2580 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2581 /// - 1 means test decl with no name.
2582 /// - if there is a 0 byte at the position `name` indexes, it indicates
2583 /// this is a test decl, and the name starts at `name+1`.
2584 /// value: Index,
2585 /// align: Ref, // if corresponding bit is set
2586 /// link_section: Ref, // if corresponding bit is set
2587 /// }
2588 pub const OpaqueDecl = struct {
2589 decls_len: u32,
2590 };
2591
2592 /// Trailing: field_name: u32 // for every field: null terminated string index
2593 pub const ErrorSetDecl = struct {
2594 fields_len: u32,
2595 };
2596
2597 /// A f128 value, broken up into 4 u32 parts.
2598 pub const Float128 = struct {
2599 piece0: u32,
2600 piece1: u32,
2601 piece2: u32,
2602 piece3: u32,
2603
2604 pub fn get(self: Float128) f128 {
2605 const int_bits = @as(u128, self.piece0) |
2606 (@as(u128, self.piece1) << 32) |
2607 (@as(u128, self.piece2) << 64) |
2608 (@as(u128, self.piece3) << 96);
2609 return @bitCast(f128, int_bits);
2610 }
2611 };
2612
2613 /// Trailing is an item per field.
2614 pub const StructInit = struct {
2615 fields_len: u32,
2616
2617 pub const Item = struct {
2618 /// The `field_type` ZIR instruction for this field init.
2619 field_type: Index,
2620 /// The field init expression to be used as the field value.
2621 init: Ref,
2622 };
2623 };
2624
2625 /// Trailing is an item per field.
2626 pub const StructInitAnon = struct {
2627 fields_len: u32,
2628
2629 pub const Item = struct {
2630 /// Null-terminated string table index.
2631 field_name: u32,
2632 /// The field init expression to be used as the field value.
2633 init: Ref,
2634 };
2635 };
2636
2637 pub const FieldType = struct {
2638 container_type: Ref,
2639 /// Offset into `string_bytes`, null terminated.
2640 name_start: u32,
2641 };
2642
2643 pub const FieldTypeRef = struct {
2644 container_type: Ref,
2645 field_name: Ref,
2646 };
2647
2648 pub const OverflowArithmetic = struct {
2649 node: i32,
2650 lhs: Ref,
2651 rhs: Ref,
2652 ptr: Ref,
2653 };
2654
2655 pub const Cmpxchg = struct {
2656 ptr: Ref,
2657 expected_value: Ref,
2658 new_value: Ref,
2659 success_order: Ref,
2660 fail_order: Ref,
2661 };
2662
2663 pub const AtomicRmw = struct {
2664 ptr: Ref,
2665 operation: Ref,
2666 operand: Ref,
2667 ordering: Ref,
2668 };
2669
2670 pub const UnionInitPtr = struct {
2671 result_ptr: Ref,
2672 union_type: Ref,
2673 field_name: Ref,
2674 };
2675
2676 pub const AtomicStore = struct {
2677 ptr: Ref,
2678 operand: Ref,
2679 ordering: Ref,
2680 };
2681
2682 pub const MulAdd = struct {
2683 mulend1: Ref,
2684 mulend2: Ref,
2685 addend: Ref,
2686 };
2687
2688 pub const FieldParentPtr = struct {
2689 parent_type: Ref,
2690 field_name: Ref,
2691 field_ptr: Ref,
2692 };
2693
2694 pub const Memcpy = struct {
2695 dest: Ref,
2696 source: Ref,
2697 byte_count: Ref,
2698 };
2699
2700 pub const Memset = struct {
2701 dest: Ref,
2702 byte: Ref,
2703 byte_count: Ref,
2704 };
2705
2706 pub const Shuffle = struct {
2707 elem_type: Ref,
2708 a: Ref,
2709 b: Ref,
2710 mask: Ref,
2711 };
2712
2713 pub const AsyncCall = struct {
2714 frame_buffer: Ref,
2715 result_ptr: Ref,
2716 fn_ptr: Ref,
2717 args: Ref,
2718 };
2719
2720 /// Trailing:
2721 /// 0. type_inst: Ref, // if small 0b000X is set
2722 /// 1. align_inst: Ref, // if small 0b00X0 is set
2723 pub const AllocExtended = struct {
2724 src_node: i32,
2725 };
2726
2727 pub const Export = struct {
2728 /// Null-terminated string index.
2729 decl_name: u32,
2730 options: Ref,
2731 };
2732
2733 /// Trailing: `CompileErrors.Item` for each `items_len`.
2734 pub const CompileErrors = struct {
2735 items_len: u32,
2736
2737 /// Trailing: `note_payload_index: u32` for each `notes_len`.
2738 /// It's a payload index of another `Item`.
2739 pub const Item = struct {
2740 /// null terminated string index
2741 msg: u32,
2742 node: ast.Node.Index,
2743 /// If node is 0 then this will be populated.
2744 token: ast.TokenIndex,
2745 /// Can be used in combination with `token`.
2746 byte_offset: u32,
2747 /// 0 or a payload index of a `Block`, each is a payload
2748 /// index of another `Item`.
2749 notes: u32,
2750 };
2751 };
2752
2753 /// Trailing: for each `imports_len` there is a string table index.
2754 pub const Imports = struct {
2755 imports_len: u32,
2756 };
2757};
2758
2759pub const SpecialProng = enum { none, @"else", under };
2760
2761const Writer = struct {
2762 gpa: *Allocator,
2763 arena: *Allocator,
2764 file: *Module.Scope.File,
2765 code: Zir,
2766 indent: u32,
2767 parent_decl_node: u32,
2768
2769 fn relativeToNodeIndex(self: *Writer, offset: i32) ast.Node.Index {
2770 return @bitCast(ast.Node.Index, offset + @bitCast(i32, self.parent_decl_node));
2771 }
2772
2773 fn writeInstToStream(
2774 self: *Writer,
2775 stream: anytype,
2776 inst: Inst.Index,
2777 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
2778 const tags = self.code.instructions.items(.tag);
2779 const tag = tags[inst];
2780 try stream.print("= {s}(", .{@tagName(tags[inst])});
2781 switch (tag) {
2782 .array_type,
2783 .as,
2784 .coerce_result_ptr,
2785 .elem_ptr,
2786 .elem_val,
2787 .store,
2788 .store_to_block_ptr,
2789 .store_to_inferred_ptr,
2790 .field_ptr_type,
2791 => try self.writeBin(stream, inst),
2792
2793 .alloc,
2794 .alloc_mut,
2795 .alloc_comptime,
2796 .indexable_ptr_len,
2797 .anyframe_type,
2798 .bit_not,
2799 .bool_not,
2800 .negate,
2801 .negate_wrap,
2802 .load,
2803 .ensure_result_used,
2804 .ensure_result_non_error,
2805 .ret_node,
2806 .resolve_inferred_alloc,
2807 .optional_type,
2808 .optional_payload_safe,
2809 .optional_payload_unsafe,
2810 .optional_payload_safe_ptr,
2811 .optional_payload_unsafe_ptr,
2812 .err_union_payload_safe,
2813 .err_union_payload_unsafe,
2814 .err_union_payload_safe_ptr,
2815 .err_union_payload_unsafe_ptr,
2816 .err_union_code,
2817 .err_union_code_ptr,
2818 .is_non_null,
2819 .is_null,
2820 .is_non_null_ptr,
2821 .is_null_ptr,
2822 .is_err,
2823 .is_err_ptr,
2824 .typeof,
2825 .typeof_elem,
2826 .struct_init_empty,
2827 .type_info,
2828 .size_of,
2829 .bit_size_of,
2830 .typeof_log2_int_type,
2831 .log2_int_type,
2832 .ptr_to_int,
2833 .error_to_int,
2834 .int_to_error,
2835 .compile_error,
2836 .set_eval_branch_quota,
2837 .enum_to_int,
2838 .align_of,
2839 .bool_to_int,
2840 .embed_file,
2841 .error_name,
2842 .panic,
2843 .set_align_stack,
2844 .set_cold,
2845 .set_float_mode,
2846 .set_runtime_safety,
2847 .sqrt,
2848 .sin,
2849 .cos,
2850 .exp,
2851 .exp2,
2852 .log,
2853 .log2,
2854 .log10,
2855 .fabs,
2856 .floor,
2857 .ceil,
2858 .trunc,
2859 .round,
2860 .tag_name,
2861 .reify,
2862 .type_name,
2863 .frame_type,
2864 .frame_size,
2865 .clz,
2866 .ctz,
2867 .pop_count,
2868 .byte_swap,
2869 .bit_reverse,
2870 .elem_type,
2871 .@"resume",
2872 .@"await",
2873 .await_nosuspend,
2874 => try self.writeUnNode(stream, inst),
2875
2876 .ref,
2877 .ret_coerce,
2878 .ensure_err_payload_void,
2879 => try self.writeUnTok(stream, inst),
2880
2881 .bool_br_and,
2882 .bool_br_or,
2883 => try self.writeBoolBr(stream, inst),
2884
2885 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
2886 .param_type => try self.writeParamType(stream, inst),
2887 .ptr_type_simple => try self.writePtrTypeSimple(stream, inst),
2888 .ptr_type => try self.writePtrType(stream, inst),
2889 .int => try self.writeInt(stream, inst),
2890 .int_big => try self.writeIntBig(stream, inst),
2891 .float => try self.writeFloat(stream, inst),
2892 .float128 => try self.writeFloat128(stream, inst),
2893 .str => try self.writeStr(stream, inst),
2894 .int_type => try self.writeIntType(stream, inst),
2895
2896 .@"break",
2897 .break_inline,
2898 => try self.writeBreak(stream, inst),
2899
2900 .elem_ptr_node,
2901 .elem_val_node,
2902 .field_ptr_named,
2903 .field_val_named,
2904 .slice_start,
2905 .slice_end,
2906 .slice_sentinel,
2907 .array_init,
2908 .array_init_anon,
2909 .array_init_ref,
2910 .array_init_anon_ref,
2911 .union_init_ptr,
2912 .cmpxchg_strong,
2913 .cmpxchg_weak,
2914 .shuffle,
2915 .atomic_rmw,
2916 .atomic_store,
2917 .mul_add,
2918 .builtin_call,
2919 .field_parent_ptr,
2920 .memcpy,
2921 .memset,
2922 .builtin_async_call,
2923 => try self.writePlNode(stream, inst),
2924
2925 .struct_init,
2926 .struct_init_ref,
2927 => try self.writeStructInit(stream, inst),
2928
2929 .struct_init_anon,
2930 .struct_init_anon_ref,
2931 => try self.writeStructInitAnon(stream, inst),
2932
2933 .field_type => try self.writeFieldType(stream, inst),
2934 .field_type_ref => try self.writeFieldTypeRef(stream, inst),
2935
2936 .add,
2937 .addwrap,
2938 .array_cat,
2939 .array_mul,
2940 .mul,
2941 .mulwrap,
2942 .sub,
2943 .subwrap,
2944 .bool_and,
2945 .bool_or,
2946 .cmp_lt,
2947 .cmp_lte,
2948 .cmp_eq,
2949 .cmp_gte,
2950 .cmp_gt,
2951 .cmp_neq,
2952 .div,
2953 .has_decl,
2954 .has_field,
2955 .mod_rem,
2956 .shl,
2957 .shl_exact,
2958 .shr,
2959 .shr_exact,
2960 .xor,
2961 .store_node,
2962 .error_union_type,
2963 .merge_error_sets,
2964 .bit_and,
2965 .bit_or,
2966 .float_to_int,
2967 .int_to_float,
2968 .int_to_ptr,
2969 .int_to_enum,
2970 .float_cast,
2971 .int_cast,
2972 .err_set_cast,
2973 .ptr_cast,
2974 .truncate,
2975 .align_cast,
2976 .div_exact,
2977 .div_floor,
2978 .div_trunc,
2979 .mod,
2980 .rem,
2981 .bit_offset_of,
2982 .byte_offset_of,
2983 .splat,
2984 .reduce,
2985 .atomic_load,
2986 .bitcast,
2987 .bitcast_result_ptr,
2988 .vector_type,
2989 => try self.writePlNodeBin(stream, inst),
2990
2991 .@"export" => try self.writePlNodeExport(stream, inst),
2992
2993 .call,
2994 .call_chkused,
2995 .call_compile_time,
2996 .call_nosuspend,
2997 .call_async,
2998 => try self.writePlNodeCall(stream, inst),
2999
3000 .block,
3001 .block_inline,
3002 .suspend_block,
3003 .loop,
3004 .validate_struct_init_ptr,
3005 .validate_array_init_ptr,
3006 .c_import,
3007 => try self.writePlNodeBlock(stream, inst),
3008
3009 .condbr,
3010 .condbr_inline,
3011 => try self.writePlNodeCondBr(stream, inst),
3012
3013 .opaque_decl => try self.writeOpaqueDecl(stream, inst, .parent),
3014 .opaque_decl_anon => try self.writeOpaqueDecl(stream, inst, .anon),
3015 .opaque_decl_func => try self.writeOpaqueDecl(stream, inst, .func),
3016
3017 .error_set_decl => try self.writeErrorSetDecl(stream, inst, .parent),
3018 .error_set_decl_anon => try self.writeErrorSetDecl(stream, inst, .anon),
3019 .error_set_decl_func => try self.writeErrorSetDecl(stream, inst, .func),
3020
3021 .switch_block => try self.writePlNodeSwitchBr(stream, inst, .none),
3022 .switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),
3023 .switch_block_under => try self.writePlNodeSwitchBr(stream, inst, .under),
3024 .switch_block_ref => try self.writePlNodeSwitchBr(stream, inst, .none),
3025 .switch_block_ref_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),
3026 .switch_block_ref_under => try self.writePlNodeSwitchBr(stream, inst, .under),
3027
3028 .switch_block_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .none),
3029 .switch_block_else_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .@"else"),
3030 .switch_block_under_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .under),
3031 .switch_block_ref_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .none),
3032 .switch_block_ref_else_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .@"else"),
3033 .switch_block_ref_under_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .under),
3034
3035 .field_ptr,
3036 .field_val,
3037 => try self.writePlNodeField(stream, inst),
3038
3039 .as_node => try self.writeAs(stream, inst),
3040
3041 .breakpoint,
3042 .fence,
3043 .repeat,
3044 .repeat_inline,
3045 .alloc_inferred,
3046 .alloc_inferred_mut,
3047 .alloc_inferred_comptime,
3048 => try self.writeNode(stream, inst),
3049
3050 .error_value,
3051 .enum_literal,
3052 .decl_ref,
3053 .decl_val,
3054 .import,
3055 .arg,
3056 => try self.writeStrTok(stream, inst),
3057
3058 .func => try self.writeFunc(stream, inst, false),
3059 .func_inferred => try self.writeFunc(stream, inst, true),
3060
3061 .@"unreachable" => try self.writeUnreachable(stream, inst),
3062
3063 .switch_capture,
3064 .switch_capture_ref,
3065 .switch_capture_multi,
3066 .switch_capture_multi_ref,
3067 .switch_capture_else,
3068 .switch_capture_else_ref,
3069 => try self.writeSwitchCapture(stream, inst),
3070
3071 .dbg_stmt => try self.writeDbgStmt(stream, inst),
3072
3073 .extended => try self.writeExtended(stream, inst),
3074 }
3075 }
3076
3077 fn writeExtended(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3078 const extended = self.code.instructions.items(.data)[inst].extended;
3079 try stream.print("{s}(", .{@tagName(extended.opcode)});
3080 switch (extended.opcode) {
3081 .ret_ptr,
3082 .ret_type,
3083 .this,
3084 .ret_addr,
3085 .error_return_trace,
3086 .frame,
3087 .frame_address,
3088 .builtin_src,
3089 => try self.writeExtNode(stream, extended),
3090
3091 .@"asm" => try self.writeAsm(stream, extended),
3092 .func => try self.writeFuncExtended(stream, extended),
3093 .variable => try self.writeVarExtended(stream, extended),
3094
3095 .compile_log,
3096 .typeof_peer,
3097 => try self.writeNodeMultiOp(stream, extended),
3098
3099 .add_with_overflow,
3100 .sub_with_overflow,
3101 .mul_with_overflow,
3102 .shl_with_overflow,
3103 => try self.writeOverflowArithmetic(stream, extended),
3104
3105 .struct_decl => try self.writeStructDecl(stream, extended),
3106 .union_decl => try self.writeUnionDecl(stream, extended),
3107 .enum_decl => try self.writeEnumDecl(stream, extended),
3108
3109 .alloc,
3110 .builtin_extern,
3111 .c_undef,
3112 .c_include,
3113 .c_define,
3114 .wasm_memory_size,
3115 .wasm_memory_grow,
3116 => try stream.writeAll("TODO))"),
3117 }
3118 }
3119
3120 fn writeExtNode(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3121 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
3122 try stream.writeAll(")) ");
3123 try self.writeSrc(stream, src);
3124 }
3125
3126 fn writeBin(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3127 const inst_data = self.code.instructions.items(.data)[inst].bin;
3128 try self.writeInstRef(stream, inst_data.lhs);
3129 try stream.writeAll(", ");
3130 try self.writeInstRef(stream, inst_data.rhs);
3131 try stream.writeByte(')');
3132 }
3133
3134 fn writeUnNode(
3135 self: *Writer,
3136 stream: anytype,
3137 inst: Inst.Index,
3138 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
3139 const inst_data = self.code.instructions.items(.data)[inst].un_node;
3140 try self.writeInstRef(stream, inst_data.operand);
3141 try stream.writeAll(") ");
3142 try self.writeSrc(stream, inst_data.src());
3143 }
3144
3145 fn writeUnTok(
3146 self: *Writer,
3147 stream: anytype,
3148 inst: Inst.Index,
3149 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
3150 const inst_data = self.code.instructions.items(.data)[inst].un_tok;
3151 try self.writeInstRef(stream, inst_data.operand);
3152 try stream.writeAll(") ");
3153 try self.writeSrc(stream, inst_data.src());
3154 }
3155
3156 fn writeArrayTypeSentinel(
3157 self: *Writer,
3158 stream: anytype,
3159 inst: Inst.Index,
3160 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
3161 const inst_data = self.code.instructions.items(.data)[inst].array_type_sentinel;
3162 try stream.writeAll("TODO)");
3163 }
3164
3165 fn writeParamType(
3166 self: *Writer,
3167 stream: anytype,
3168 inst: Inst.Index,
3169 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
3170 const inst_data = self.code.instructions.items(.data)[inst].param_type;
3171 try self.writeInstRef(stream, inst_data.callee);
3172 try stream.print(", {d})", .{inst_data.param_index});
3173 }
3174
3175 fn writePtrTypeSimple(
3176 self: *Writer,
3177 stream: anytype,
3178 inst: Inst.Index,
3179 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
3180 const inst_data = self.code.instructions.items(.data)[inst].ptr_type_simple;
3181 const str_allowzero = if (inst_data.is_allowzero) "allowzero, " else "";
3182 const str_const = if (!inst_data.is_mutable) "const, " else "";
3183 const str_volatile = if (inst_data.is_volatile) "volatile, " else "";
3184 try self.writeInstRef(stream, inst_data.elem_type);
3185 try stream.print(", {s}{s}{s}{s})", .{
3186 str_allowzero,
3187 str_const,
3188 str_volatile,
3189 @tagName(inst_data.size),
3190 });
3191 }
3192
3193 fn writePtrType(
3194 self: *Writer,
3195 stream: anytype,
3196 inst: Inst.Index,
3197 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
3198 const inst_data = self.code.instructions.items(.data)[inst].ptr_type;
3199 try stream.writeAll("TODO)");
3200 }
3201
3202 fn writeInt(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3203 const inst_data = self.code.instructions.items(.data)[inst].int;
3204 try stream.print("{d})", .{inst_data});
3205 }
3206
3207 fn writeIntBig(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3208 const inst_data = self.code.instructions.items(.data)[inst].str;
3209 const byte_count = inst_data.len * @sizeOf(std.math.big.Limb);
3210 const limb_bytes = self.code.string_bytes[inst_data.start..][0..byte_count];
3211 // limb_bytes is not aligned properly; we must allocate and copy the bytes
3212 // in order to accomplish this.
3213 const limbs = try self.gpa.alloc(std.math.big.Limb, inst_data.len);
3214 defer self.gpa.free(limbs);
3215
3216 mem.copy(u8, mem.sliceAsBytes(limbs), limb_bytes);
3217 const big_int: std.math.big.int.Const = .{
3218 .limbs = limbs,
3219 .positive = true,
3220 };
3221 const as_string = try big_int.toStringAlloc(self.gpa, 10, false);
3222 defer self.gpa.free(as_string);
3223 try stream.print("{s})", .{as_string});
3224 }
3225
3226 fn writeFloat(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3227 const inst_data = self.code.instructions.items(.data)[inst].float;
3228 const src = inst_data.src();
3229 try stream.print("{d}) ", .{inst_data.number});
3230 try self.writeSrc(stream, src);
3231 }
3232
3233 fn writeFloat128(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3234 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3235 const extra = self.code.extraData(Inst.Float128, inst_data.payload_index).data;
3236 const src = inst_data.src();
3237 const number = extra.get();
3238 // TODO improve std.format to be able to print f128 values
3239 try stream.print("{d}) ", .{@floatCast(f64, number)});
3240 try self.writeSrc(stream, src);
3241 }
3242
3243 fn writeStr(
3244 self: *Writer,
3245 stream: anytype,
3246 inst: Inst.Index,
3247 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
3248 const inst_data = self.code.instructions.items(.data)[inst].str;
3249 const str = inst_data.get(self.code);
3250 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});
3251 }
3252
3253 fn writePlNode(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3254 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3255 try stream.writeAll("TODO) ");
3256 try self.writeSrc(stream, inst_data.src());
3257 }
3258
3259 fn writePlNodeBin(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3260 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3261 const extra = self.code.extraData(Inst.Bin, inst_data.payload_index).data;
3262 try self.writeInstRef(stream, extra.lhs);
3263 try stream.writeAll(", ");
3264 try self.writeInstRef(stream, extra.rhs);
3265 try stream.writeAll(") ");
3266 try self.writeSrc(stream, inst_data.src());
3267 }
3268
3269 fn writePlNodeExport(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3270 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3271 const extra = self.code.extraData(Inst.Export, inst_data.payload_index).data;
3272 const decl_name = self.code.nullTerminatedString(extra.decl_name);
3273
3274 try stream.print("{}, ", .{std.zig.fmtId(decl_name)});
3275 try self.writeInstRef(stream, extra.options);
3276 try stream.writeAll(") ");
3277 try self.writeSrc(stream, inst_data.src());
3278 }
3279
3280 fn writeStructInit(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3281 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3282 const extra = self.code.extraData(Inst.StructInit, inst_data.payload_index);
3283 var field_i: u32 = 0;
3284 var extra_index = extra.end;
3285
3286 while (field_i < extra.data.fields_len) : (field_i += 1) {
3287 const item = self.code.extraData(Inst.StructInit.Item, extra_index);
3288 extra_index = item.end;
3289
3290 if (field_i != 0) {
3291 try stream.writeAll(", [");
3292 } else {
3293 try stream.writeAll("[");
3294 }
3295 try self.writeInstIndex(stream, item.data.field_type);
3296 try stream.writeAll(", ");
3297 try self.writeInstRef(stream, item.data.init);
3298 try stream.writeAll("]");
3299 }
3300 try stream.writeAll(") ");
3301 try self.writeSrc(stream, inst_data.src());
3302 }
3303
3304 fn writeStructInitAnon(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3305 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3306 const extra = self.code.extraData(Inst.StructInitAnon, inst_data.payload_index);
3307 var field_i: u32 = 0;
3308 var extra_index = extra.end;
3309
3310 while (field_i < extra.data.fields_len) : (field_i += 1) {
3311 const item = self.code.extraData(Inst.StructInitAnon.Item, extra_index);
3312 extra_index = item.end;
3313
3314 const field_name = self.code.nullTerminatedString(item.data.field_name);
3315
3316 const prefix = if (field_i != 0) ", [" else "[";
3317 try stream.print("{s}[{s}=", .{ prefix, field_name });
3318 try self.writeInstRef(stream, item.data.init);
3319 try stream.writeAll("]");
3320 }
3321 try stream.writeAll(") ");
3322 try self.writeSrc(stream, inst_data.src());
3323 }
3324
3325 fn writeFieldType(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3326 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3327 const extra = self.code.extraData(Inst.FieldType, inst_data.payload_index).data;
3328 try self.writeInstRef(stream, extra.container_type);
3329 const field_name = self.code.nullTerminatedString(extra.name_start);
3330 try stream.print(", {s}) ", .{field_name});
3331 try self.writeSrc(stream, inst_data.src());
3332 }
3333
3334 fn writeFieldTypeRef(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3335 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3336 const extra = self.code.extraData(Inst.FieldTypeRef, inst_data.payload_index).data;
3337 try self.writeInstRef(stream, extra.container_type);
3338 try stream.writeAll(", ");
3339 try self.writeInstRef(stream, extra.field_name);
3340 try stream.writeAll(") ");
3341 try self.writeSrc(stream, inst_data.src());
3342 }
3343
3344 fn writeNodeMultiOp(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3345 const extra = self.code.extraData(Inst.NodeMultiOp, extended.operand);
3346 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
3347 const operands = self.code.refSlice(extra.end, extended.small);
3348
3349 for (operands) |operand, i| {
3350 if (i != 0) try stream.writeAll(", ");
3351 try self.writeInstRef(stream, operand);
3352 }
3353 try stream.writeAll(")) ");
3354 try self.writeSrc(stream, src);
3355 }
3356
3357 fn writeAsm(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3358 const extra = self.code.extraData(Inst.Asm, extended.operand);
3359 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
3360 const outputs_len = @truncate(u5, extended.small);
3361 const inputs_len = @truncate(u5, extended.small >> 5);
3362 const clobbers_len = @truncate(u5, extended.small >> 10);
3363 const is_volatile = @truncate(u1, extended.small >> 15) != 0;
3364
3365 try self.writeFlag(stream, "volatile, ", is_volatile);
3366 try self.writeInstRef(stream, extra.data.asm_source);
3367 try stream.writeAll(", ");
3368
3369 var extra_i: usize = extra.end;
3370 var output_type_bits = extra.data.output_type_bits;
3371 {
3372 var i: usize = 0;
3373 while (i < outputs_len) : (i += 1) {
3374 const output = self.code.extraData(Inst.Asm.Output, extra_i);
3375 extra_i = output.end;
3376
3377 const is_type = @truncate(u1, output_type_bits) != 0;
3378 output_type_bits >>= 1;
3379
3380 const name = self.code.nullTerminatedString(output.data.name);
3381 const constraint = self.code.nullTerminatedString(output.data.constraint);
3382 try stream.print("output({}, \"{}\", ", .{
3383 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),
3384 });
3385 try self.writeFlag(stream, "->", is_type);
3386 try self.writeInstRef(stream, output.data.operand);
3387 try stream.writeAll(")");
3388 if (i + 1 < outputs_len) {
3389 try stream.writeAll("), ");
3390 }
3391 }
3392 }
3393 {
3394 var i: usize = 0;
3395 while (i < inputs_len) : (i += 1) {
3396 const input = self.code.extraData(Inst.Asm.Input, extra_i);
3397 extra_i = input.end;
3398
3399 const name = self.code.nullTerminatedString(input.data.name);
3400 const constraint = self.code.nullTerminatedString(input.data.constraint);
3401 try stream.print("input({}, \"{}\", ", .{
3402 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),
3403 });
3404 try self.writeInstRef(stream, input.data.operand);
3405 try stream.writeAll(")");
3406 if (i + 1 < inputs_len) {
3407 try stream.writeAll(", ");
3408 }
3409 }
3410 }
3411 {
3412 var i: usize = 0;
3413 while (i < clobbers_len) : (i += 1) {
3414 const str_index = self.code.extra[extra_i];
3415 extra_i += 1;
3416 const clobber = self.code.nullTerminatedString(str_index);
3417 try stream.print("{}", .{std.zig.fmtId(clobber)});
3418 if (i + 1 < clobbers_len) {
3419 try stream.writeAll(", ");
3420 }
3421 }
3422 }
3423 try stream.writeAll(")) ");
3424 try self.writeSrc(stream, src);
3425 }
3426
3427 fn writeOverflowArithmetic(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3428 const extra = self.code.extraData(Zir.Inst.OverflowArithmetic, extended.operand).data;
3429 const src: LazySrcLoc = .{ .node_offset = extra.node };
3430
3431 try self.writeInstRef(stream, extra.lhs);
3432 try stream.writeAll(", ");
3433 try self.writeInstRef(stream, extra.rhs);
3434 try stream.writeAll(", ");
3435 try self.writeInstRef(stream, extra.ptr);
3436 try stream.writeAll(")) ");
3437 try self.writeSrc(stream, src);
3438 }
3439
3440 fn writePlNodeCall(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3441 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3442 const extra = self.code.extraData(Inst.Call, inst_data.payload_index);
3443 const args = self.code.refSlice(extra.end, extra.data.args_len);
3444
3445 try self.writeInstRef(stream, extra.data.callee);
3446 try stream.writeAll(", [");
3447 for (args) |arg, i| {
3448 if (i != 0) try stream.writeAll(", ");
3449 try self.writeInstRef(stream, arg);
3450 }
3451 try stream.writeAll("]) ");
3452 try self.writeSrc(stream, inst_data.src());
3453 }
3454
3455 fn writePlNodeBlock(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3456 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3457 try self.writePlNodeBlockWithoutSrc(stream, inst);
3458 try self.writeSrc(stream, inst_data.src());
3459 }
3460
3461 fn writePlNodeBlockWithoutSrc(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3462 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3463 const extra = self.code.extraData(Inst.Block, inst_data.payload_index);
3464 const body = self.code.extra[extra.end..][0..extra.data.body_len];
3465 try stream.writeAll("{\n");
3466 self.indent += 2;
3467 try self.writeBody(stream, body);
3468 self.indent -= 2;
3469 try stream.writeByteNTimes(' ', self.indent);
3470 try stream.writeAll("}) ");
3471 }
3472
3473 fn writePlNodeCondBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3474 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3475 const extra = self.code.extraData(Inst.CondBr, inst_data.payload_index);
3476 const then_body = self.code.extra[extra.end..][0..extra.data.then_body_len];
3477 const else_body = self.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
3478 try self.writeInstRef(stream, extra.data.condition);
3479 try stream.writeAll(", {\n");
3480 self.indent += 2;
3481 try self.writeBody(stream, then_body);
3482 self.indent -= 2;
3483 try stream.writeByteNTimes(' ', self.indent);
3484 try stream.writeAll("}, {\n");
3485 self.indent += 2;
3486 try self.writeBody(stream, else_body);
3487 self.indent -= 2;
3488 try stream.writeByteNTimes(' ', self.indent);
3489 try stream.writeAll("}) ");
3490 try self.writeSrc(stream, inst_data.src());
3491 }
3492
3493 fn writeStructDecl(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3494 const small = @bitCast(Inst.StructDecl.Small, extended.small);
3495
3496 var extra_index: usize = extended.operand;
3497
3498 const src_node: ?i32 = if (small.has_src_node) blk: {
3499 const src_node = @bitCast(i32, self.code.extra[extra_index]);
3500 extra_index += 1;
3501 break :blk src_node;
3502 } else null;
3503
3504 const body_len = if (small.has_body_len) blk: {
3505 const body_len = self.code.extra[extra_index];
3506 extra_index += 1;
3507 break :blk body_len;
3508 } else 0;
3509
3510 const fields_len = if (small.has_fields_len) blk: {
3511 const fields_len = self.code.extra[extra_index];
3512 extra_index += 1;
3513 break :blk fields_len;
3514 } else 0;
3515
3516 const decls_len = if (small.has_decls_len) blk: {
3517 const decls_len = self.code.extra[extra_index];
3518 extra_index += 1;
3519 break :blk decls_len;
3520 } else 0;
3521
3522 try stream.print("{s}, {s}, ", .{
3523 @tagName(small.name_strategy), @tagName(small.layout),
3524 });
3525
3526 if (decls_len == 0) {
3527 try stream.writeAll("{}, ");
3528 } else {
3529 try stream.writeAll("{\n");
3530 self.indent += 2;
3531 extra_index = try self.writeDecls(stream, decls_len, extra_index);
3532 self.indent -= 2;
3533 try stream.writeByteNTimes(' ', self.indent);
3534 try stream.writeAll("}, ");
3535 }
3536
3537 const body = self.code.extra[extra_index..][0..body_len];
3538 extra_index += body.len;
3539
3540 if (fields_len == 0) {
3541 assert(body.len == 0);
3542 try stream.writeAll("{}, {})");
3543 } else {
3544 self.indent += 2;
3545 if (body.len == 0) {
3546 try stream.writeAll("{}, {\n");
3547 } else {
3548 try stream.writeAll("{\n");
3549 try self.writeBody(stream, body);
3550
3551 try stream.writeByteNTimes(' ', self.indent - 2);
3552 try stream.writeAll("}, {\n");
3553 }
3554
3555 const bits_per_field = 4;
3556 const fields_per_u32 = 32 / bits_per_field;
3557 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
3558 var bit_bag_index: usize = extra_index;
3559 extra_index += bit_bags_count;
3560 var cur_bit_bag: u32 = undefined;
3561 var field_i: u32 = 0;
3562 while (field_i < fields_len) : (field_i += 1) {
3563 if (field_i % fields_per_u32 == 0) {
3564 cur_bit_bag = self.code.extra[bit_bag_index];
3565 bit_bag_index += 1;
3566 }
3567 const has_align = @truncate(u1, cur_bit_bag) != 0;
3568 cur_bit_bag >>= 1;
3569 const has_default = @truncate(u1, cur_bit_bag) != 0;
3570 cur_bit_bag >>= 1;
3571 const is_comptime = @truncate(u1, cur_bit_bag) != 0;
3572 cur_bit_bag >>= 1;
3573 const unused = @truncate(u1, cur_bit_bag) != 0;
3574 cur_bit_bag >>= 1;
3575
3576 _ = unused;
3577
3578 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
3579 extra_index += 1;
3580 const field_type = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
3581 extra_index += 1;
3582
3583 try stream.writeByteNTimes(' ', self.indent);
3584 try self.writeFlag(stream, "comptime ", is_comptime);
3585 try stream.print("{}: ", .{std.zig.fmtId(field_name)});
3586 try self.writeInstRef(stream, field_type);
3587
3588 if (has_align) {
3589 const align_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
3590 extra_index += 1;
3591
3592 try stream.writeAll(" align(");
3593 try self.writeInstRef(stream, align_ref);
3594 try stream.writeAll(")");
3595 }
3596 if (has_default) {
3597 const default_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
3598 extra_index += 1;
3599
3600 try stream.writeAll(" = ");
3601 try self.writeInstRef(stream, default_ref);
3602 }
3603 try stream.writeAll(",\n");
3604 }
3605
3606 self.indent -= 2;
3607 try stream.writeByteNTimes(' ', self.indent);
3608 try stream.writeAll("})");
3609 }
3610 try self.writeSrcNode(stream, src_node);
3611 }
3612
3613 fn writeUnionDecl(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3614 const small = @bitCast(Inst.UnionDecl.Small, extended.small);
3615
3616 var extra_index: usize = extended.operand;
3617
3618 const src_node: ?i32 = if (small.has_src_node) blk: {
3619 const src_node = @bitCast(i32, self.code.extra[extra_index]);
3620 extra_index += 1;
3621 break :blk src_node;
3622 } else null;
3623
3624 const tag_type_ref = if (small.has_tag_type) blk: {
3625 const tag_type_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
3626 extra_index += 1;
3627 break :blk tag_type_ref;
3628 } else .none;
3629
3630 const body_len = if (small.has_body_len) blk: {
3631 const body_len = self.code.extra[extra_index];
3632 extra_index += 1;
3633 break :blk body_len;
3634 } else 0;
3635
3636 const fields_len = if (small.has_fields_len) blk: {
3637 const fields_len = self.code.extra[extra_index];
3638 extra_index += 1;
3639 break :blk fields_len;
3640 } else 0;
3641
3642 const decls_len = if (small.has_decls_len) blk: {
3643 const decls_len = self.code.extra[extra_index];
3644 extra_index += 1;
3645 break :blk decls_len;
3646 } else 0;
3647
3648 try stream.print("{s}, {s}, ", .{
3649 @tagName(small.name_strategy), @tagName(small.layout),
3650 });
3651 try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag);
3652
3653 if (decls_len == 0) {
3654 try stream.writeAll("{}, ");
3655 } else {
3656 try stream.writeAll("{\n");
3657 self.indent += 2;
3658 extra_index = try self.writeDecls(stream, decls_len, extra_index);
3659 self.indent -= 2;
3660 try stream.writeByteNTimes(' ', self.indent);
3661 try stream.writeAll("}, ");
3662 }
3663
3664 assert(fields_len != 0);
3665
3666 if (tag_type_ref != .none) {
3667 try self.writeInstRef(stream, tag_type_ref);
3668 try stream.writeAll(", ");
3669 }
3670
3671 const body = self.code.extra[extra_index..][0..body_len];
3672 extra_index += body.len;
3673
3674 self.indent += 2;
3675 if (body.len == 0) {
3676 try stream.writeAll("{}, {\n");
3677 } else {
3678 try stream.writeAll("{\n");
3679 try self.writeBody(stream, body);
3680
3681 try stream.writeByteNTimes(' ', self.indent - 2);
3682 try stream.writeAll("}, {\n");
3683 }
3684
3685 const bits_per_field = 4;
3686 const fields_per_u32 = 32 / bits_per_field;
3687 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
3688 const body_end = extra_index;
3689 extra_index += bit_bags_count;
3690 var bit_bag_index: usize = body_end;
3691 var cur_bit_bag: u32 = undefined;
3692 var field_i: u32 = 0;
3693 while (field_i < fields_len) : (field_i += 1) {
3694 if (field_i % fields_per_u32 == 0) {
3695 cur_bit_bag = self.code.extra[bit_bag_index];
3696 bit_bag_index += 1;
3697 }
3698 const has_type = @truncate(u1, cur_bit_bag) != 0;
3699 cur_bit_bag >>= 1;
3700 const has_align = @truncate(u1, cur_bit_bag) != 0;
3701 cur_bit_bag >>= 1;
3702 const has_value = @truncate(u1, cur_bit_bag) != 0;
3703 cur_bit_bag >>= 1;
3704 const unused = @truncate(u1, cur_bit_bag) != 0;
3705 cur_bit_bag >>= 1;
3706
3707 _ = unused;
3708
3709 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
3710 extra_index += 1;
3711 try stream.writeByteNTimes(' ', self.indent);
3712 try stream.print("{}", .{std.zig.fmtId(field_name)});
3713
3714 if (has_type) {
3715 const field_type = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
3716 extra_index += 1;
3717
3718 try stream.writeAll(": ");
3719 try self.writeInstRef(stream, field_type);
3720 }
3721 if (has_align) {
3722 const align_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
3723 extra_index += 1;
3724
3725 try stream.writeAll(" align(");
3726 try self.writeInstRef(stream, align_ref);
3727 try stream.writeAll(")");
3728 }
3729 if (has_value) {
3730 const default_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
3731 extra_index += 1;
3732
3733 try stream.writeAll(" = ");
3734 try self.writeInstRef(stream, default_ref);
3735 }
3736 try stream.writeAll(",\n");
3737 }
3738
3739 self.indent -= 2;
3740 try stream.writeByteNTimes(' ', self.indent);
3741 try stream.writeAll("})");
3742 try self.writeSrcNode(stream, src_node);
3743 }
3744
3745 fn writeDecls(self: *Writer, stream: anytype, decls_len: u32, extra_start: usize) !usize {
3746 const parent_decl_node = self.parent_decl_node;
3747 const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable;
3748 var extra_index = extra_start + bit_bags_count;
3749 var bit_bag_index: usize = extra_start;
3750 var cur_bit_bag: u32 = undefined;
3751 var decl_i: u32 = 0;
3752 while (decl_i < decls_len) : (decl_i += 1) {
3753 if (decl_i % 8 == 0) {
3754 cur_bit_bag = self.code.extra[bit_bag_index];
3755 bit_bag_index += 1;
3756 }
3757 const is_pub = @truncate(u1, cur_bit_bag) != 0;
3758 cur_bit_bag >>= 1;
3759 const is_exported = @truncate(u1, cur_bit_bag) != 0;
3760 cur_bit_bag >>= 1;
3761 const has_align = @truncate(u1, cur_bit_bag) != 0;
3762 cur_bit_bag >>= 1;
3763 const has_section = @truncate(u1, cur_bit_bag) != 0;
3764 cur_bit_bag >>= 1;
3765
3766 const sub_index = extra_index;
3767
3768 const hash_u32s = self.code.extra[extra_index..][0..4];
3769 extra_index += 4;
3770 const line = self.code.extra[extra_index];
3771 extra_index += 1;
3772 const decl_name_index = self.code.extra[extra_index];
3773 extra_index += 1;
3774 const decl_index = self.code.extra[extra_index];
3775 extra_index += 1;
3776 const align_inst: Inst.Ref = if (!has_align) .none else inst: {
3777 const inst = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
3778 extra_index += 1;
3779 break :inst inst;
3780 };
3781 const section_inst: Inst.Ref = if (!has_section) .none else inst: {
3782 const inst = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
3783 extra_index += 1;
3784 break :inst inst;
3785 };
3786
3787 const pub_str = if (is_pub) "pub " else "";
3788 const hash_bytes = @bitCast([16]u8, hash_u32s.*);
3789 try stream.writeByteNTimes(' ', self.indent);
3790 if (decl_name_index == 0) {
3791 const name = if (is_exported) "usingnamespace" else "comptime";
3792 try stream.writeAll(pub_str);
3793 try stream.writeAll(name);
3794 } else if (decl_name_index == 1) {
3795 try stream.writeAll("test");
3796 } else {
3797 const raw_decl_name = self.code.nullTerminatedString(decl_name_index);
3798 const decl_name = if (raw_decl_name.len == 0)
3799 self.code.nullTerminatedString(decl_name_index + 1)
3800 else
3801 raw_decl_name;
3802 const test_str = if (raw_decl_name.len == 0) "test " else "";
3803 const export_str = if (is_exported) "export " else "";
3804 try stream.print("[{d}] {s}{s}{s}{}", .{
3805 sub_index, pub_str, test_str, export_str, std.zig.fmtId(decl_name),
3806 });
3807 if (align_inst != .none) {
3808 try stream.writeAll(" align(");
3809 try self.writeInstRef(stream, align_inst);
3810 try stream.writeAll(")");
3811 }
3812 if (section_inst != .none) {
3813 try stream.writeAll(" linksection(");
3814 try self.writeInstRef(stream, section_inst);
3815 try stream.writeAll(")");
3816 }
3817 }
3818 const tag = self.code.instructions.items(.tag)[decl_index];
3819 try stream.print(" line({d}) hash({}): %{d} = {s}(", .{
3820 line, std.fmt.fmtSliceHexLower(&hash_bytes), decl_index, @tagName(tag),
3821 });
3822
3823 const decl_block_inst_data = self.code.instructions.items(.data)[decl_index].pl_node;
3824 const sub_decl_node_off = decl_block_inst_data.src_node;
3825 self.parent_decl_node = self.relativeToNodeIndex(sub_decl_node_off);
3826 try self.writePlNodeBlockWithoutSrc(stream, decl_index);
3827 self.parent_decl_node = parent_decl_node;
3828 try self.writeSrc(stream, decl_block_inst_data.src());
3829 try stream.writeAll("\n");
3830 }
3831 return extra_index;
3832 }
3833
3834 fn writeEnumDecl(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3835 const small = @bitCast(Inst.EnumDecl.Small, extended.small);
3836 var extra_index: usize = extended.operand;
3837
3838 const src_node: ?i32 = if (small.has_src_node) blk: {
3839 const src_node = @bitCast(i32, self.code.extra[extra_index]);
3840 extra_index += 1;
3841 break :blk src_node;
3842 } else null;
3843
3844 const tag_type_ref = if (small.has_tag_type) blk: {
3845 const tag_type_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
3846 extra_index += 1;
3847 break :blk tag_type_ref;
3848 } else .none;
3849
3850 const body_len = if (small.has_body_len) blk: {
3851 const body_len = self.code.extra[extra_index];
3852 extra_index += 1;
3853 break :blk body_len;
3854 } else 0;
3855
3856 const fields_len = if (small.has_fields_len) blk: {
3857 const fields_len = self.code.extra[extra_index];
3858 extra_index += 1;
3859 break :blk fields_len;
3860 } else 0;
3861
3862 const decls_len = if (small.has_decls_len) blk: {
3863 const decls_len = self.code.extra[extra_index];
3864 extra_index += 1;
3865 break :blk decls_len;
3866 } else 0;
3867
3868 try stream.print("{s}, ", .{@tagName(small.name_strategy)});
3869 try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive);
3870
3871 if (decls_len == 0) {
3872 try stream.writeAll("{}, ");
3873 } else {
3874 try stream.writeAll("{\n");
3875 self.indent += 2;
3876 extra_index = try self.writeDecls(stream, decls_len, extra_index);
3877 self.indent -= 2;
3878 try stream.writeByteNTimes(' ', self.indent);
3879 try stream.writeAll("}, ");
3880 }
3881
3882 if (tag_type_ref != .none) {
3883 try self.writeInstRef(stream, tag_type_ref);
3884 try stream.writeAll(", ");
3885 }
3886
3887 const body = self.code.extra[extra_index..][0..body_len];
3888 extra_index += body.len;
3889
3890 if (fields_len == 0) {
3891 assert(body.len == 0);
3892 try stream.writeAll("{}, {})");
3893 } else {
3894 self.indent += 2;
3895 if (body.len == 0) {
3896 try stream.writeAll("{}, {\n");
3897 } else {
3898 try stream.writeAll("{\n");
3899 try self.writeBody(stream, body);
3900
3901 try stream.writeByteNTimes(' ', self.indent - 2);
3902 try stream.writeAll("}, {\n");
3903 }
3904
3905 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
3906 const body_end = extra_index;
3907 extra_index += bit_bags_count;
3908 var bit_bag_index: usize = body_end;
3909 var cur_bit_bag: u32 = undefined;
3910 var field_i: u32 = 0;
3911 while (field_i < fields_len) : (field_i += 1) {
3912 if (field_i % 32 == 0) {
3913 cur_bit_bag = self.code.extra[bit_bag_index];
3914 bit_bag_index += 1;
3915 }
3916 const has_tag_value = @truncate(u1, cur_bit_bag) != 0;
3917 cur_bit_bag >>= 1;
3918
3919 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
3920 extra_index += 1;
3921
3922 try stream.writeByteNTimes(' ', self.indent);
3923 try stream.print("{}", .{std.zig.fmtId(field_name)});
3924
3925 if (has_tag_value) {
3926 const tag_value_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
3927 extra_index += 1;
3928
3929 try stream.writeAll(" = ");
3930 try self.writeInstRef(stream, tag_value_ref);
3931 }
3932 try stream.writeAll(",\n");
3933 }
3934 self.indent -= 2;
3935 try stream.writeByteNTimes(' ', self.indent);
3936 try stream.writeAll("})");
3937 }
3938 try self.writeSrcNode(stream, src_node);
3939 }
3940
3941 fn writeOpaqueDecl(
3942 self: *Writer,
3943 stream: anytype,
3944 inst: Inst.Index,
3945 name_strategy: Inst.NameStrategy,
3946 ) !void {
3947 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3948 const extra = self.code.extraData(Inst.OpaqueDecl, inst_data.payload_index);
3949 const decls_len = extra.data.decls_len;
3950
3951 try stream.print("{s}, ", .{@tagName(name_strategy)});
3952
3953 if (decls_len == 0) {
3954 try stream.writeAll("}) ");
3955 } else {
3956 try stream.writeAll("\n");
3957 self.indent += 2;
3958 _ = try self.writeDecls(stream, decls_len, extra.end);
3959 self.indent -= 2;
3960 try stream.writeByteNTimes(' ', self.indent);
3961 try stream.writeAll("}) ");
3962 }
3963 try self.writeSrc(stream, inst_data.src());
3964 }
3965
3966 fn writeErrorSetDecl(
3967 self: *Writer,
3968 stream: anytype,
3969 inst: Inst.Index,
3970 name_strategy: Inst.NameStrategy,
3971 ) !void {
3972 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3973 const extra = self.code.extraData(Inst.ErrorSetDecl, inst_data.payload_index);
3974 const fields = self.code.extra[extra.end..][0..extra.data.fields_len];
3975
3976 try stream.print("{s}, ", .{@tagName(name_strategy)});
3977
3978 try stream.writeAll("{\n");
3979 self.indent += 2;
3980 for (fields) |str_index| {
3981 const name = self.code.nullTerminatedString(str_index);
3982 try stream.writeByteNTimes(' ', self.indent);
3983 try stream.print("{},\n", .{std.zig.fmtId(name)});
3984 }
3985 self.indent -= 2;
3986 try stream.writeByteNTimes(' ', self.indent);
3987 try stream.writeAll("}) ");
3988
3989 try self.writeSrc(stream, inst_data.src());
3990 }
3991
3992 fn writePlNodeSwitchBr(
3993 self: *Writer,
3994 stream: anytype,
3995 inst: Inst.Index,
3996 special_prong: SpecialProng,
3997 ) !void {
3998 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3999 const extra = self.code.extraData(Inst.SwitchBlock, inst_data.payload_index);
4000 const special: struct {
4001 body: []const Inst.Index,
4002 end: usize,
4003 } = switch (special_prong) {
4004 .none => .{ .body = &.{}, .end = extra.end },
4005 .under, .@"else" => blk: {
4006 const body_len = self.code.extra[extra.end];
4007 const extra_body_start = extra.end + 1;
4008 break :blk .{
4009 .body = self.code.extra[extra_body_start..][0..body_len],
4010 .end = extra_body_start + body_len,
4011 };
4012 },
4013 };
4014
4015 try self.writeInstRef(stream, extra.data.operand);
4016
4017 if (special.body.len != 0) {
4018 const prong_name = switch (special_prong) {
4019 .@"else" => "else",
4020 .under => "_",
4021 else => unreachable,
4022 };
4023 try stream.print(", {s} => {{\n", .{prong_name});
4024 self.indent += 2;
4025 try self.writeBody(stream, special.body);
4026 self.indent -= 2;
4027 try stream.writeByteNTimes(' ', self.indent);
4028 try stream.writeAll("}");
4029 }
4030
4031 var extra_index: usize = special.end;
4032 {
4033 var scalar_i: usize = 0;
4034 while (scalar_i < extra.data.cases_len) : (scalar_i += 1) {
4035 const item_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
4036 extra_index += 1;
4037 const body_len = self.code.extra[extra_index];
4038 extra_index += 1;
4039 const body = self.code.extra[extra_index..][0..body_len];
4040 extra_index += body_len;
4041
4042 try stream.writeAll(", ");
4043 try self.writeInstRef(stream, item_ref);
4044 try stream.writeAll(" => {\n");
4045 self.indent += 2;
4046 try self.writeBody(stream, body);
4047 self.indent -= 2;
4048 try stream.writeByteNTimes(' ', self.indent);
4049 try stream.writeAll("}");
4050 }
4051 }
4052 try stream.writeAll(") ");
4053 try self.writeSrc(stream, inst_data.src());
4054 }
4055
4056 fn writePlNodeSwitchBlockMulti(
4057 self: *Writer,
4058 stream: anytype,
4059 inst: Inst.Index,
4060 special_prong: SpecialProng,
4061 ) !void {
4062 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
4063 const extra = self.code.extraData(Inst.SwitchBlockMulti, inst_data.payload_index);
4064 const special: struct {
4065 body: []const Inst.Index,
4066 end: usize,
4067 } = switch (special_prong) {
4068 .none => .{ .body = &.{}, .end = extra.end },
4069 .under, .@"else" => blk: {
4070 const body_len = self.code.extra[extra.end];
4071 const extra_body_start = extra.end + 1;
4072 break :blk .{
4073 .body = self.code.extra[extra_body_start..][0..body_len],
4074 .end = extra_body_start + body_len,
4075 };
4076 },
4077 };
4078
4079 try self.writeInstRef(stream, extra.data.operand);
4080
4081 if (special.body.len != 0) {
4082 const prong_name = switch (special_prong) {
4083 .@"else" => "else",
4084 .under => "_",
4085 else => unreachable,
4086 };
4087 try stream.print(", {s} => {{\n", .{prong_name});
4088 self.indent += 2;
4089 try self.writeBody(stream, special.body);
4090 self.indent -= 2;
4091 try stream.writeByteNTimes(' ', self.indent);
4092 try stream.writeAll("}");
4093 }
4094
4095 var extra_index: usize = special.end;
4096 {
4097 var scalar_i: usize = 0;
4098 while (scalar_i < extra.data.scalar_cases_len) : (scalar_i += 1) {
4099 const item_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
4100 extra_index += 1;
4101 const body_len = self.code.extra[extra_index];
4102 extra_index += 1;
4103 const body = self.code.extra[extra_index..][0..body_len];
4104 extra_index += body_len;
4105
4106 try stream.writeAll(", ");
4107 try self.writeInstRef(stream, item_ref);
4108 try stream.writeAll(" => {\n");
4109 self.indent += 2;
4110 try self.writeBody(stream, body);
4111 self.indent -= 2;
4112 try stream.writeByteNTimes(' ', self.indent);
4113 try stream.writeAll("}");
4114 }
4115 }
4116 {
4117 var multi_i: usize = 0;
4118 while (multi_i < extra.data.multi_cases_len) : (multi_i += 1) {
4119 const items_len = self.code.extra[extra_index];
4120 extra_index += 1;
4121 const ranges_len = self.code.extra[extra_index];
4122 extra_index += 1;
4123 const body_len = self.code.extra[extra_index];
4124 extra_index += 1;
4125 const items = self.code.refSlice(extra_index, items_len);
4126 extra_index += items_len;
4127
4128 for (items) |item_ref| {
4129 try stream.writeAll(", ");
4130 try self.writeInstRef(stream, item_ref);
4131 }
4132
4133 var range_i: usize = 0;
4134 while (range_i < ranges_len) : (range_i += 1) {
4135 const item_first = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
4136 extra_index += 1;
4137 const item_last = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
4138 extra_index += 1;
4139
4140 try stream.writeAll(", ");
4141 try self.writeInstRef(stream, item_first);
4142 try stream.writeAll("...");
4143 try self.writeInstRef(stream, item_last);
4144 }
4145
4146 const body = self.code.extra[extra_index..][0..body_len];
4147 extra_index += body_len;
4148 try stream.writeAll(" => {\n");
4149 self.indent += 2;
4150 try self.writeBody(stream, body);
4151 self.indent -= 2;
4152 try stream.writeByteNTimes(' ', self.indent);
4153 try stream.writeAll("}");
4154 }
4155 }
4156 try stream.writeAll(") ");
4157 try self.writeSrc(stream, inst_data.src());
4158 }
4159
4160 fn writePlNodeField(self: *Writer, stream: anytype, inst: Inst.Index) !void {
4161 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
4162 const extra = self.code.extraData(Inst.Field, inst_data.payload_index).data;
4163 const name = self.code.nullTerminatedString(extra.field_name_start);
4164 try self.writeInstRef(stream, extra.lhs);
4165 try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(name)});
4166 try self.writeSrc(stream, inst_data.src());
4167 }
4168
4169 fn writeAs(self: *Writer, stream: anytype, inst: Inst.Index) !void {
4170 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
4171 const extra = self.code.extraData(Inst.As, inst_data.payload_index).data;
4172 try self.writeInstRef(stream, extra.dest_type);
4173 try stream.writeAll(", ");
4174 try self.writeInstRef(stream, extra.operand);
4175 try stream.writeAll(") ");
4176 try self.writeSrc(stream, inst_data.src());
4177 }
4178
4179 fn writeNode(
4180 self: *Writer,
4181 stream: anytype,
4182 inst: Inst.Index,
4183 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
4184 const src_node = self.code.instructions.items(.data)[inst].node;
4185 const src: LazySrcLoc = .{ .node_offset = src_node };
4186 try stream.writeAll(") ");
4187 try self.writeSrc(stream, src);
4188 }
4189
4190 fn writeStrTok(
4191 self: *Writer,
4192 stream: anytype,
4193 inst: Inst.Index,
4194 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
4195 const inst_data = self.code.instructions.items(.data)[inst].str_tok;
4196 const str = inst_data.get(self.code);
4197 try stream.print("\"{}\") ", .{std.zig.fmtEscapes(str)});
4198 try self.writeSrc(stream, inst_data.src());
4199 }
4200
4201 fn writeFunc(
4202 self: *Writer,
4203 stream: anytype,
4204 inst: Inst.Index,
4205 inferred_error_set: bool,
4206 ) !void {
4207 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
4208 const src = inst_data.src();
4209 const extra = self.code.extraData(Inst.Func, inst_data.payload_index);
4210 const param_types = self.code.refSlice(extra.end, extra.data.param_types_len);
4211 const body = self.code.extra[extra.end + param_types.len ..][0..extra.data.body_len];
4212 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
4213 if (body.len != 0) {
4214 const extra_index = extra.end + param_types.len + body.len;
4215 src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
4216 }
4217 return self.writeFuncCommon(
4218 stream,
4219 param_types,
4220 extra.data.return_type,
4221 inferred_error_set,
4222 false,
4223 false,
4224 .none,
4225 .none,
4226 body,
4227 src,
4228 src_locs,
4229 );
4230 }
4231
4232 fn writeFuncExtended(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
4233 const extra = self.code.extraData(Inst.ExtendedFunc, extended.operand);
4234 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
4235 const small = @bitCast(Inst.ExtendedFunc.Small, extended.small);
4236
4237 var extra_index: usize = extra.end;
4238 if (small.has_lib_name) {
4239 const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
4240 extra_index += 1;
4241 try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});
4242 }
4243 try self.writeFlag(stream, "test, ", small.is_test);
4244 const cc: Inst.Ref = if (!small.has_cc) .none else blk: {
4245 const cc = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
4246 extra_index += 1;
4247 break :blk cc;
4248 };
4249 const align_inst: Inst.Ref = if (!small.has_align) .none else blk: {
4250 const align_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
4251 extra_index += 1;
4252 break :blk align_inst;
4253 };
4254
4255 const param_types = self.code.refSlice(extra_index, extra.data.param_types_len);
4256 extra_index += param_types.len;
4257
4258 const body = self.code.extra[extra_index..][0..extra.data.body_len];
4259 extra_index += body.len;
4260
4261 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
4262 if (body.len != 0) {
4263 src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
4264 }
4265 return self.writeFuncCommon(
4266 stream,
4267 param_types,
4268 extra.data.return_type,
4269 small.is_inferred_error,
4270 small.is_var_args,
4271 small.is_extern,
4272 cc,
4273 align_inst,
4274 body,
4275 src,
4276 src_locs,
4277 );
4278 }
4279
4280 fn writeVarExtended(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
4281 const extra = self.code.extraData(Inst.ExtendedVar, extended.operand);
4282 const small = @bitCast(Inst.ExtendedVar.Small, extended.small);
4283
4284 try self.writeInstRef(stream, extra.data.var_type);
4285
4286 var extra_index: usize = extra.end;
4287 if (small.has_lib_name) {
4288 const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
4289 extra_index += 1;
4290 try stream.print(", lib_name=\"{}\"", .{std.zig.fmtEscapes(lib_name)});
4291 }
4292 const align_inst: Inst.Ref = if (!small.has_align) .none else blk: {
4293 const align_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
4294 extra_index += 1;
4295 break :blk align_inst;
4296 };
4297 const init_inst: Inst.Ref = if (!small.has_init) .none else blk: {
4298 const init_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
4299 extra_index += 1;
4300 break :blk init_inst;
4301 };
4302 try self.writeFlag(stream, ", is_extern", small.is_extern);
4303 try self.writeOptionalInstRef(stream, ", align=", align_inst);
4304 try self.writeOptionalInstRef(stream, ", init=", init_inst);
4305 try stream.writeAll("))");
4306 }
4307
4308 fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
4309 const inst_data = self.code.instructions.items(.data)[inst].bool_br;
4310 const extra = self.code.extraData(Inst.Block, inst_data.payload_index);
4311 const body = self.code.extra[extra.end..][0..extra.data.body_len];
4312 try self.writeInstRef(stream, inst_data.lhs);
4313 try stream.writeAll(", {\n");
4314 self.indent += 2;
4315 try self.writeBody(stream, body);
4316 self.indent -= 2;
4317 try stream.writeByteNTimes(' ', self.indent);
4318 try stream.writeAll("})");
4319 }
4320
4321 fn writeIntType(self: *Writer, stream: anytype, inst: Inst.Index) !void {
4322 const int_type = self.code.instructions.items(.data)[inst].int_type;
4323 const prefix: u8 = switch (int_type.signedness) {
4324 .signed => 'i',
4325 .unsigned => 'u',
4326 };
4327 try stream.print("{c}{d}) ", .{ prefix, int_type.bit_count });
4328 try self.writeSrc(stream, int_type.src());
4329 }
4330
4331 fn writeBreak(self: *Writer, stream: anytype, inst: Inst.Index) !void {
4332 const inst_data = self.code.instructions.items(.data)[inst].@"break";
4333
4334 try self.writeInstIndex(stream, inst_data.block_inst);
4335 try stream.writeAll(", ");
4336 try self.writeInstRef(stream, inst_data.operand);
4337 try stream.writeAll(")");
4338 }
4339
4340 fn writeUnreachable(self: *Writer, stream: anytype, inst: Inst.Index) !void {
4341 const inst_data = self.code.instructions.items(.data)[inst].@"unreachable";
4342 const safety_str = if (inst_data.safety) "safe" else "unsafe";
4343 try stream.print("{s}) ", .{safety_str});
4344 try self.writeSrc(stream, inst_data.src());
4345 }
4346
4347 fn writeFuncCommon(
4348 self: *Writer,
4349 stream: anytype,
4350 param_types: []const Inst.Ref,
4351 ret_ty: Inst.Ref,
4352 inferred_error_set: bool,
4353 var_args: bool,
4354 is_extern: bool,
4355 cc: Inst.Ref,
4356 align_inst: Inst.Ref,
4357 body: []const Inst.Index,
4358 src: LazySrcLoc,
4359 src_locs: Zir.Inst.Func.SrcLocs,
4360 ) !void {
4361 try stream.writeAll("[");
4362 for (param_types) |param_type, i| {
4363 if (i != 0) try stream.writeAll(", ");
4364 try self.writeInstRef(stream, param_type);
4365 }
4366 try stream.writeAll("], ");
4367 try self.writeInstRef(stream, ret_ty);
4368 try self.writeOptionalInstRef(stream, ", cc=", cc);
4369 try self.writeOptionalInstRef(stream, ", align=", align_inst);
4370 try self.writeFlag(stream, ", vargs", var_args);
4371 try self.writeFlag(stream, ", extern", is_extern);
4372 try self.writeFlag(stream, ", inferror", inferred_error_set);
4373
4374 if (body.len == 0) {
4375 try stream.writeAll(", {}) ");
4376 } else {
4377 try stream.writeAll(", {\n");
4378 self.indent += 2;
4379 try self.writeBody(stream, body);
4380 self.indent -= 2;
4381 try stream.writeByteNTimes(' ', self.indent);
4382 try stream.writeAll("}) ");
4383 }
4384 if (body.len != 0) {
4385 try stream.print("(lbrace={d}:{d},rbrace={d}:{d}) ", .{
4386 src_locs.lbrace_line, @truncate(u16, src_locs.columns),
4387 src_locs.rbrace_line, @truncate(u16, src_locs.columns >> 16),
4388 });
4389 }
4390 try self.writeSrc(stream, src);
4391 }
4392
4393 fn writeSwitchCapture(self: *Writer, stream: anytype, inst: Inst.Index) !void {
4394 const inst_data = self.code.instructions.items(.data)[inst].switch_capture;
4395 try self.writeInstIndex(stream, inst_data.switch_inst);
4396 try stream.print(", {d})", .{inst_data.prong_index});
4397 }
4398
4399 fn writeDbgStmt(self: *Writer, stream: anytype, inst: Inst.Index) !void {
4400 const inst_data = self.code.instructions.items(.data)[inst].dbg_stmt;
4401 try stream.print("{d}, {d})", .{ inst_data.line, inst_data.column });
4402 }
4403
4404 fn writeInstRef(self: *Writer, stream: anytype, ref: Inst.Ref) !void {
4405 var i: usize = @enumToInt(ref);
4406
4407 if (i < Inst.Ref.typed_value_map.len) {
4408 return stream.print("@{}", .{ref});
4409 }
4410 i -= Inst.Ref.typed_value_map.len;
4411
4412 return self.writeInstIndex(stream, @intCast(Inst.Index, i));
4413 }
4414
4415 fn writeInstIndex(self: *Writer, stream: anytype, inst: Inst.Index) !void {
4416 return stream.print("%{d}", .{inst});
4417 }
4418
4419 fn writeOptionalInstRef(
4420 self: *Writer,
4421 stream: anytype,
4422 prefix: []const u8,
4423 inst: Inst.Ref,
4424 ) !void {
4425 if (inst == .none) return;
4426 try stream.writeAll(prefix);
4427 try self.writeInstRef(stream, inst);
4428 }
4429
4430 fn writeFlag(
4431 self: *Writer,
4432 stream: anytype,
4433 name: []const u8,
4434 flag: bool,
4435 ) !void {
4436 if (!flag) return;
4437 try stream.writeAll(name);
4438 }
4439
4440 fn writeSrc(self: *Writer, stream: anytype, src: LazySrcLoc) !void {
4441 const tree = self.file.tree;
4442 const src_loc: Module.SrcLoc = .{
4443 .file_scope = self.file,
4444 .parent_decl_node = self.parent_decl_node,
4445 .lazy = src,
4446 };
4447 // Caller must ensure AST tree is loaded.
4448 const abs_byte_off = src_loc.byteOffset(self.gpa) catch unreachable;
4449 const delta_line = std.zig.findLineColumn(tree.source, abs_byte_off);
4450 try stream.print("{s}:{d}:{d}", .{
4451 @tagName(src), delta_line.line + 1, delta_line.column + 1,
4452 });
4453 }
4454
4455 fn writeSrcNode(self: *Writer, stream: anytype, src_node: ?i32) !void {
4456 const node_offset = src_node orelse return;
4457 const src: LazySrcLoc = .{ .node_offset = node_offset };
4458 try stream.writeAll(" ");
4459 return self.writeSrc(stream, src);
4460 }
4461
4462 fn writeBody(self: *Writer, stream: anytype, body: []const Inst.Index) !void {
4463 for (body) |inst| {
4464 try stream.writeByteNTimes(' ', self.indent);
4465 try stream.print("%{d} ", .{inst});
4466 try self.writeInstToStream(stream, inst);
4467 try stream.writeByte('\n');
4468 }
4469 }
4470};
4471
4472pub const DeclIterator = struct {
4473 extra_index: usize,
4474 bit_bag_index: usize,
4475 cur_bit_bag: u32,
4476 decl_i: u32,
4477 decls_len: u32,
4478 zir: Zir,
4479
4480 pub const Item = struct {
4481 name: [:0]const u8,
4482 sub_index: u32,
4483 };
4484
4485 pub fn next(it: *DeclIterator) ?Item {
4486 if (it.decl_i >= it.decls_len) return null;
4487
4488 if (it.decl_i % 8 == 0) {
4489 it.cur_bit_bag = it.zir.extra[it.bit_bag_index];
4490 it.bit_bag_index += 1;
4491 }
4492 it.decl_i += 1;
4493
4494 const flags = @truncate(u4, it.cur_bit_bag);
4495 it.cur_bit_bag >>= 4;
4496
4497 const sub_index = @intCast(u32, it.extra_index);
4498 it.extra_index += 5; // src_hash(4) + line(1)
4499 const name = it.zir.nullTerminatedString(it.zir.extra[it.extra_index]);
4500 it.extra_index += 2; // name(1) + value(1)
4501 it.extra_index += @truncate(u1, flags >> 2);
4502 it.extra_index += @truncate(u1, flags >> 3);
4503
4504 return Item{
4505 .sub_index = sub_index,
4506 .name = name,
4507 };
4508 }
4509};
4510
4511pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {
4512 const tags = zir.instructions.items(.tag);
4513 const datas = zir.instructions.items(.data);
4514 switch (tags[decl_inst]) {
4515 .opaque_decl,
4516 .opaque_decl_anon,
4517 .opaque_decl_func,
4518 => {
4519 const inst_data = datas[decl_inst].pl_node;
4520 const extra = zir.extraData(Inst.OpaqueDecl, inst_data.payload_index);
4521 return declIteratorInner(zir, extra.end, extra.data.decls_len);
4522 },
4523
4524 // Functions are allowed and yield no iterations.
4525 // There is one case matching this in the extended instruction set below.
4526 .func,
4527 .func_inferred,
4528 => return declIteratorInner(zir, 0, 0),
4529
4530 .extended => {
4531 const extended = datas[decl_inst].extended;
4532 switch (extended.opcode) {
4533 .func => return declIteratorInner(zir, 0, 0),
4534 .struct_decl => {
4535 const small = @bitCast(Inst.StructDecl.Small, extended.small);
4536 var extra_index: usize = extended.operand;
4537 extra_index += @boolToInt(small.has_src_node);
4538 extra_index += @boolToInt(small.has_body_len);
4539 extra_index += @boolToInt(small.has_fields_len);
4540 const decls_len = if (small.has_decls_len) decls_len: {
4541 const decls_len = zir.extra[extra_index];
4542 extra_index += 1;
4543 break :decls_len decls_len;
4544 } else 0;
4545
4546 return declIteratorInner(zir, extra_index, decls_len);
4547 },
4548 .enum_decl => {
4549 const small = @bitCast(Inst.EnumDecl.Small, extended.small);
4550 var extra_index: usize = extended.operand;
4551 extra_index += @boolToInt(small.has_src_node);
4552 extra_index += @boolToInt(small.has_tag_type);
4553 extra_index += @boolToInt(small.has_body_len);
4554 extra_index += @boolToInt(small.has_fields_len);
4555 const decls_len = if (small.has_decls_len) decls_len: {
4556 const decls_len = zir.extra[extra_index];
4557 extra_index += 1;
4558 break :decls_len decls_len;
4559 } else 0;
4560
4561 return declIteratorInner(zir, extra_index, decls_len);
4562 },
4563 .union_decl => {
4564 const small = @bitCast(Inst.UnionDecl.Small, extended.small);
4565 var extra_index: usize = extended.operand;
4566 extra_index += @boolToInt(small.has_src_node);
4567 extra_index += @boolToInt(small.has_tag_type);
4568 extra_index += @boolToInt(small.has_body_len);
4569 extra_index += @boolToInt(small.has_fields_len);
4570 const decls_len = if (small.has_decls_len) decls_len: {
4571 const decls_len = zir.extra[extra_index];
4572 extra_index += 1;
4573 break :decls_len decls_len;
4574 } else 0;
4575
4576 return declIteratorInner(zir, extra_index, decls_len);
4577 },
4578 else => unreachable,
4579 }
4580 },
4581 else => unreachable,
4582 }
4583}
4584
4585pub fn declIteratorInner(zir: Zir, extra_index: usize, decls_len: u32) DeclIterator {
4586 const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable;
4587 return .{
4588 .zir = zir,
4589 .extra_index = extra_index + bit_bags_count,
4590 .bit_bag_index = extra_index,
4591 .cur_bit_bag = undefined,
4592 .decl_i = 0,
4593 .decls_len = decls_len,
4594 };
4595}
4596
4597/// The iterator would have to allocate memory anyway to iterate. So here we populate
4598/// an ArrayList as the result.
4599pub fn findDecls(zir: Zir, list: *std.ArrayList(Zir.Inst.Index), decl_sub_index: u32) !void {
4600 const block_inst = zir.extra[decl_sub_index + 6];
4601 list.clearRetainingCapacity();
4602
4603 return zir.findDeclsInner(list, block_inst);
4604}
4605
4606fn findDeclsInner(
4607 zir: Zir,
4608 list: *std.ArrayList(Zir.Inst.Index),
4609 inst: Zir.Inst.Index,
4610) Allocator.Error!void {
4611 const tags = zir.instructions.items(.tag);
4612 const datas = zir.instructions.items(.data);
4613
4614 switch (tags[inst]) {
4615 // Decl instructions are interesting but have no body.
4616 // TODO yes they do have a body actually. recurse over them just like block instructions.
4617 .opaque_decl,
4618 .opaque_decl_anon,
4619 .opaque_decl_func,
4620 => return list.append(inst),
4621
4622 // Functions instructions are interesting and have a body.
4623 .func,
4624 .func_inferred,
4625 => {
4626 try list.append(inst);
4627
4628 const inst_data = datas[inst].pl_node;
4629 const extra = zir.extraData(Inst.Func, inst_data.payload_index);
4630 const param_types_len = extra.data.param_types_len;
4631 const body = zir.extra[extra.end + param_types_len ..][0..extra.data.body_len];
4632 return zir.findDeclsBody(list, body);
4633 },
4634 .extended => {
4635 const extended = datas[inst].extended;
4636 switch (extended.opcode) {
4637 .func => {
4638 try list.append(inst);
4639
4640 const extra = zir.extraData(Inst.ExtendedFunc, extended.operand);
4641 const small = @bitCast(Inst.ExtendedFunc.Small, extended.small);
4642 var extra_index: usize = extra.end;
4643 extra_index += @boolToInt(small.has_lib_name);
4644 extra_index += @boolToInt(small.has_cc);
4645 extra_index += @boolToInt(small.has_align);
4646 extra_index += extra.data.param_types_len;
4647 const body = zir.extra[extra_index..][0..extra.data.body_len];
4648 return zir.findDeclsBody(list, body);
4649 },
4650
4651 .struct_decl,
4652 .union_decl,
4653 .enum_decl,
4654 => return list.append(inst),
4655
4656 else => return,
4657 }
4658 },
4659
4660 // Block instructions, recurse over the bodies.
4661
4662 .block, .block_inline => {
4663 const inst_data = datas[inst].pl_node;
4664 const extra = zir.extraData(Inst.Block, inst_data.payload_index);
4665 const body = zir.extra[extra.end..][0..extra.data.body_len];
4666 return zir.findDeclsBody(list, body);
4667 },
4668 .condbr, .condbr_inline => {
4669 const inst_data = datas[inst].pl_node;
4670 const extra = zir.extraData(Inst.CondBr, inst_data.payload_index);
4671 const then_body = zir.extra[extra.end..][0..extra.data.then_body_len];
4672 const else_body = zir.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
4673 try zir.findDeclsBody(list, then_body);
4674 try zir.findDeclsBody(list, else_body);
4675 },
4676 .switch_block => return findDeclsSwitch(zir, list, inst, .none),
4677 .switch_block_else => return findDeclsSwitch(zir, list, inst, .@"else"),
4678 .switch_block_under => return findDeclsSwitch(zir, list, inst, .under),
4679 .switch_block_ref => return findDeclsSwitch(zir, list, inst, .none),
4680 .switch_block_ref_else => return findDeclsSwitch(zir, list, inst, .@"else"),
4681 .switch_block_ref_under => return findDeclsSwitch(zir, list, inst, .under),
4682
4683 .switch_block_multi => return findDeclsSwitchMulti(zir, list, inst, .none),
4684 .switch_block_else_multi => return findDeclsSwitchMulti(zir, list, inst, .@"else"),
4685 .switch_block_under_multi => return findDeclsSwitchMulti(zir, list, inst, .under),
4686 .switch_block_ref_multi => return findDeclsSwitchMulti(zir, list, inst, .none),
4687 .switch_block_ref_else_multi => return findDeclsSwitchMulti(zir, list, inst, .@"else"),
4688 .switch_block_ref_under_multi => return findDeclsSwitchMulti(zir, list, inst, .under),
4689
4690 .suspend_block => @panic("TODO iterate suspend block"),
4691
4692 else => return, // Regular instruction, not interesting.
4693 }
4694}
4695
4696fn findDeclsSwitch(
4697 zir: Zir,
4698 list: *std.ArrayList(Zir.Inst.Index),
4699 inst: Zir.Inst.Index,
4700 special_prong: SpecialProng,
4701) Allocator.Error!void {
4702 const inst_data = zir.instructions.items(.data)[inst].pl_node;
4703 const extra = zir.extraData(Inst.SwitchBlock, inst_data.payload_index);
4704 const special: struct {
4705 body: []const Inst.Index,
4706 end: usize,
4707 } = switch (special_prong) {
4708 .none => .{ .body = &.{}, .end = extra.end },
4709 .under, .@"else" => blk: {
4710 const body_len = zir.extra[extra.end];
4711 const extra_body_start = extra.end + 1;
4712 break :blk .{
4713 .body = zir.extra[extra_body_start..][0..body_len],
4714 .end = extra_body_start + body_len,
4715 };
4716 },
4717 };
4718
4719 try zir.findDeclsBody(list, special.body);
4720
4721 var extra_index: usize = special.end;
4722 var scalar_i: usize = 0;
4723 while (scalar_i < extra.data.cases_len) : (scalar_i += 1) {
4724 const item_ref = @intToEnum(Inst.Ref, zir.extra[extra_index]);
4725 extra_index += 1;
4726 const body_len = zir.extra[extra_index];
4727 extra_index += 1;
4728 const body = zir.extra[extra_index..][0..body_len];
4729 extra_index += body_len;
4730
4731 try zir.findDeclsBody(list, body);
4732 }
4733}
4734
4735fn findDeclsSwitchMulti(
4736 zir: Zir,
4737 list: *std.ArrayList(Zir.Inst.Index),
4738 inst: Zir.Inst.Index,
4739 special_prong: SpecialProng,
4740) Allocator.Error!void {
4741 const inst_data = zir.instructions.items(.data)[inst].pl_node;
4742 const extra = zir.extraData(Inst.SwitchBlockMulti, inst_data.payload_index);
4743 const special: struct {
4744 body: []const Inst.Index,
4745 end: usize,
4746 } = switch (special_prong) {
4747 .none => .{ .body = &.{}, .end = extra.end },
4748 .under, .@"else" => blk: {
4749 const body_len = zir.extra[extra.end];
4750 const extra_body_start = extra.end + 1;
4751 break :blk .{
4752 .body = zir.extra[extra_body_start..][0..body_len],
4753 .end = extra_body_start + body_len,
4754 };
4755 },
4756 };
4757
4758 try zir.findDeclsBody(list, special.body);
4759
4760 var extra_index: usize = special.end;
4761 {
4762 var scalar_i: usize = 0;
4763 while (scalar_i < extra.data.scalar_cases_len) : (scalar_i += 1) {
4764 const item_ref = @intToEnum(Inst.Ref, zir.extra[extra_index]);
4765 extra_index += 1;
4766 const body_len = zir.extra[extra_index];
4767 extra_index += 1;
4768 const body = zir.extra[extra_index..][0..body_len];
4769 extra_index += body_len;
4770
4771 try zir.findDeclsBody(list, body);
4772 }
4773 }
4774 {
4775 var multi_i: usize = 0;
4776 while (multi_i < extra.data.multi_cases_len) : (multi_i += 1) {
4777 const items_len = zir.extra[extra_index];
4778 extra_index += 1;
4779 const ranges_len = zir.extra[extra_index];
4780 extra_index += 1;
4781 const body_len = zir.extra[extra_index];
4782 extra_index += 1;
4783 const items = zir.refSlice(extra_index, items_len);
4784 extra_index += items_len;
4785
4786 var range_i: usize = 0;
4787 while (range_i < ranges_len) : (range_i += 1) {
4788 const item_first = @intToEnum(Inst.Ref, zir.extra[extra_index]);
4789 extra_index += 1;
4790 const item_last = @intToEnum(Inst.Ref, zir.extra[extra_index]);
4791 extra_index += 1;
4792 }
4793
4794 const body = zir.extra[extra_index..][0..body_len];
4795 extra_index += body_len;
4796
4797 try zir.findDeclsBody(list, body);
4798 }
4799 }
4800}
4801
4802fn findDeclsBody(
4803 zir: Zir,
4804 list: *std.ArrayList(Zir.Inst.Index),
4805 body: []const Zir.Inst.Index,
4806) Allocator.Error!void {
4807 for (body) |member| {
4808 try zir.findDeclsInner(list, member);
4809 }
4810}
src/codegen.zig+70-127
...@@ -117,7 +117,6 @@ pub fn generateSymbol(...@@ -117,7 +117,6 @@ pub fn generateSymbol(
117 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),117 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
118 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),118 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
119 //.s390x => return Function(.s390x).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),119 //.s390x => return Function(.s390x).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
120 .spu_2 => return Function(.spu_2).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
121 //.tce => return Function(.tce).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),120 //.tce => return Function(.tce).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
122 //.tcele => return Function(.tcele).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),121 //.tcele => return Function(.tcele).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
123 //.thumb => return Function(.thumb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),122 //.thumb => return Function(.thumb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
...@@ -212,20 +211,50 @@ pub fn generateSymbol(...@@ -212,20 +211,50 @@ pub fn generateSymbol(
212 },211 },
213 .Int => {212 .Int => {
214 // TODO populate .debug_info for the integer213 // TODO populate .debug_info for the integer
214 const endian = bin_file.options.target.cpu.arch.endian();
215 const info = typed_value.ty.intInfo(bin_file.options.target);215 const info = typed_value.ty.intInfo(bin_file.options.target);
216 if (info.bits == 8 and info.signedness == .unsigned) {216 if (info.bits <= 8) {
217 const x = typed_value.val.toUnsignedInt();217 const x = @intCast(u8, typed_value.val.toUnsignedInt());
218 try code.append(@intCast(u8, x));218 try code.append(x);
219 return Result{ .appended = {} };219 return Result{ .appended = {} };
220 }220 }
221 return Result{221 if (info.bits > 64) {
222 .fail = try ErrorMsg.create(222 return Result{
223 bin_file.allocator,223 .fail = try ErrorMsg.create(
224 src_loc,224 bin_file.allocator,
225 "TODO implement generateSymbol for int type '{}'",225 src_loc,
226 .{typed_value.ty},226 "TODO implement generateSymbol for big ints ('{}')",
227 ),227 .{typed_value.ty},
228 };228 ),
229 };
230 }
231 switch (info.signedness) {
232 .unsigned => {
233 if (info.bits <= 16) {
234 const x = @intCast(u16, typed_value.val.toUnsignedInt());
235 mem.writeInt(u16, try code.addManyAsArray(2), x, endian);
236 } else if (info.bits <= 32) {
237 const x = @intCast(u32, typed_value.val.toUnsignedInt());
238 mem.writeInt(u32, try code.addManyAsArray(4), x, endian);
239 } else {
240 const x = typed_value.val.toUnsignedInt();
241 mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
242 }
243 },
244 .signed => {
245 if (info.bits <= 16) {
246 const x = @intCast(i16, typed_value.val.toSignedInt());
247 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
248 } else if (info.bits <= 32) {
249 const x = @intCast(i32, typed_value.val.toSignedInt());
250 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
251 } else {
252 const x = typed_value.val.toSignedInt();
253 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
254 }
255 },
256 }
257 return Result{ .appended = {} };
229 },258 },
230 else => |t| {259 else => |t| {
231 return Result{260 return Result{
...@@ -266,14 +295,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -266,14 +295,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
266 src_loc: Module.SrcLoc,295 src_loc: Module.SrcLoc,
267 stack_align: u32,296 stack_align: u32,
268297
269 /// Byte offset within the source file.298 prev_di_line: u32,
270 prev_di_src: usize,299 prev_di_column: u32,
300 /// Byte offset within the source file of the ending curly.
301 end_di_line: u32,
302 end_di_column: u32,
271 /// Relative to the beginning of `code`.303 /// Relative to the beginning of `code`.
272 prev_di_pc: usize,304 prev_di_pc: usize,
273 /// Used to find newlines and count line deltas.
274 source: []const u8,
275 /// Byte offset within the source file of the ending curly.
276 rbrace_src: usize,
277305
278 /// The value is an offset into the `Function` `code` from the beginning.306 /// The value is an offset into the `Function` `code` from the beginning.
279 /// To perform the reloc, write 32-bit signed little-endian integer307 /// To perform the reloc, write 32-bit signed little-endian integer
...@@ -402,7 +430,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -402,7 +430,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
402430
403 const module_fn = typed_value.val.castTag(.function).?.data;431 const module_fn = typed_value.val.castTag(.function).?.data;
404432
405 const fn_type = module_fn.owner_decl.typed_value.most_recent.typed_value.ty;433 assert(module_fn.owner_decl.has_tv);
434 const fn_type = module_fn.owner_decl.ty;
406435
407 var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);436 var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);
408 defer {437 defer {
...@@ -412,25 +441,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -412,25 +441,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
412 }441 }
413 try branch_stack.append(.{});442 try branch_stack.append(.{});
414443
415 const src_data: struct { lbrace_src: usize, rbrace_src: usize, source: []const u8 } = blk: {
416 const container_scope = module_fn.owner_decl.container;
417 const tree = container_scope.file_scope.tree;
418 const node_tags = tree.nodes.items(.tag);
419 const node_datas = tree.nodes.items(.data);
420 const token_starts = tree.tokens.items(.start);
421
422 const fn_decl = module_fn.owner_decl.src_node;
423 assert(node_tags[fn_decl] == .fn_decl);
424 const block = node_datas[fn_decl].rhs;
425 const lbrace_src = token_starts[tree.firstToken(block)];
426 const rbrace_src = token_starts[tree.lastToken(block)];
427 break :blk .{
428 .lbrace_src = lbrace_src,
429 .rbrace_src = rbrace_src,
430 .source = tree.source,
431 };
432 };
433
434 var function = Self{444 var function = Self{
435 .gpa = bin_file.allocator,445 .gpa = bin_file.allocator,
436 .target = &bin_file.options.target,446 .target = &bin_file.options.target,
...@@ -447,9 +457,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -447,9 +457,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
447 .src_loc = src_loc,457 .src_loc = src_loc,
448 .stack_align = undefined,458 .stack_align = undefined,
449 .prev_di_pc = 0,459 .prev_di_pc = 0,
450 .prev_di_src = src_data.lbrace_src,460 .prev_di_line = module_fn.lbrace_line,
451 .rbrace_src = src_data.rbrace_src,461 .prev_di_column = module_fn.lbrace_column,
452 .source = src_data.source,462 .end_di_line = module_fn.rbrace_line,
463 .end_di_column = module_fn.rbrace_column,
453 };464 };
454 defer function.stack.deinit(bin_file.allocator);465 defer function.stack.deinit(bin_file.allocator);
455 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);466 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
...@@ -702,7 +713,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -702,7 +713,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
702 },713 },
703 }714 }
704 // Drop them off at the rbrace.715 // Drop them off at the rbrace.
705 try self.dbgAdvancePCAndLine(self.rbrace_src);716 try self.dbgAdvancePCAndLine(self.end_di_line, self.end_di_column);
706 }717 }
707718
708 fn genBody(self: *Self, body: ir.Body) InnerError!void {719 fn genBody(self: *Self, body: ir.Body) InnerError!void {
...@@ -728,7 +739,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -728,7 +739,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
728 switch (self.debug_output) {739 switch (self.debug_output) {
729 .dwarf => |dbg_out| {740 .dwarf => |dbg_out| {
730 try dbg_out.dbg_line.append(DW.LNS_set_prologue_end);741 try dbg_out.dbg_line.append(DW.LNS_set_prologue_end);
731 try self.dbgAdvancePCAndLine(self.prev_di_src);742 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
732 },743 },
733 .none => {},744 .none => {},
734 }745 }
...@@ -738,27 +749,21 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -738,27 +749,21 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
738 switch (self.debug_output) {749 switch (self.debug_output) {
739 .dwarf => |dbg_out| {750 .dwarf => |dbg_out| {
740 try dbg_out.dbg_line.append(DW.LNS_set_epilogue_begin);751 try dbg_out.dbg_line.append(DW.LNS_set_epilogue_begin);
741 try self.dbgAdvancePCAndLine(self.prev_di_src);752 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
742 },753 },
743 .none => {},754 .none => {},
744 }755 }
745 }756 }
746757
747 fn dbgAdvancePCAndLine(self: *Self, abs_byte_off: usize) InnerError!void {758 fn dbgAdvancePCAndLine(self: *Self, line: u32, column: u32) InnerError!void {
748 self.prev_di_src = abs_byte_off;
749 self.prev_di_pc = self.code.items.len;
750 switch (self.debug_output) {759 switch (self.debug_output) {
751 .dwarf => |dbg_out| {760 .dwarf => |dbg_out| {
752 // TODO Look into improving the performance here by adding a token-index-to-line761 const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line);
753 // lookup table, and changing ir.Inst from storing byte offset to token. Currently
754 // this involves scanning over the source code for newlines
755 // (but only from the previous byte offset to the new one).
756 const delta_line = std.zig.lineDelta(self.source, self.prev_di_src, abs_byte_off);
757 const delta_pc = self.code.items.len - self.prev_di_pc;762 const delta_pc = self.code.items.len - self.prev_di_pc;
758 // TODO Look into using the DWARF special opcodes to compress this data. It lets you emit763 // TODO Look into using the DWARF special opcodes to compress this data.
759 // single-byte opcodes that add different numbers to both the PC and the line number764 // It lets you emit single-byte opcodes that add different numbers to
760 // at the same time.765 // both the PC and the line number at the same time.
761 try dbg_out.dbg_line.ensureCapacity(dbg_out.dbg_line.items.len + 11);766 try dbg_out.dbg_line.ensureUnusedCapacity(11);
762 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_advance_pc);767 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_advance_pc);
763 leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable;768 leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable;
764 if (delta_line != 0) {769 if (delta_line != 0) {
...@@ -769,6 +774,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -769,6 +774,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
769 },774 },
770 .none => {},775 .none => {},
771 }776 }
777 self.prev_di_line = line;
778 self.prev_di_column = column;
779 self.prev_di_pc = self.code.items.len;
772 }780 }
773781
774 /// Asserts there is already capacity to insert into top branch inst_table.782 /// Asserts there is already capacity to insert into top branch inst_table.
...@@ -2230,11 +2238,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2230,11 +2238,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2230 .riscv64 => {2238 .riscv64 => {
2231 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ebreak.toU32());2239 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ebreak.toU32());
2232 },2240 },
2233 .spu_2 => {
2234 try self.code.resize(self.code.items.len + 2);
2235 var instr = Instruction{ .condition = .always, .input0 = .zero, .input1 = .zero, .modify_flags = false, .output = .discard, .command = .undefined1 };
2236 mem.writeIntLittle(u16, self.code.items[self.code.items.len - 2 ..][0..2], @bitCast(u16, instr));
2237 },
2238 .arm, .armeb => {2241 .arm, .armeb => {
2239 writeInt(u32, try self.code.addManyAsArray(4), Instruction.bkpt(0).toU32());2242 writeInt(u32, try self.code.addManyAsArray(4), Instruction.bkpt(0).toU32());
2240 },2243 },
...@@ -2343,52 +2346,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2343,52 +2346,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2343 return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{});2346 return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{});
2344 }2347 }
2345 },2348 },
2346 .spu_2 => {
2347 if (inst.func.value()) |func_value| {
2348 if (info.args.len != 0) {
2349 return self.fail(inst.base.src, "TODO implement call with more than 0 parameters", .{});
2350 }
2351 if (func_value.castTag(.function)) |func_payload| {
2352 const func = func_payload.data;
2353 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
2354 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
2355 break :blk @intCast(u16, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * 2);
2356 } else if (self.bin_file.cast(link.File.Coff)) |coff_file|
2357 @intCast(u16, coff_file.offset_table_virtual_address + func.owner_decl.link.coff.offset_table_index * 2)
2358 else
2359 unreachable;
2360
2361 const return_type = func.owner_decl.typed_value.most_recent.typed_value.ty.fnReturnType();
2362 // First, push the return address, then jump; if noreturn, don't bother with the first step
2363 // TODO: implement packed struct -> u16 at comptime and move the bitcast here
2364 var instr = Instruction{ .condition = .always, .input0 = .immediate, .input1 = .zero, .modify_flags = false, .output = .jump, .command = .load16 };
2365 if (return_type.zigTypeTag() == .NoReturn) {
2366 try self.code.resize(self.code.items.len + 4);
2367 mem.writeIntLittle(u16, self.code.items[self.code.items.len - 4 ..][0..2], @bitCast(u16, instr));
2368 mem.writeIntLittle(u16, self.code.items[self.code.items.len - 2 ..][0..2], got_addr);
2369 return MCValue.unreach;
2370 } else {
2371 try self.code.resize(self.code.items.len + 8);
2372 var push = Instruction{ .condition = .always, .input0 = .immediate, .input1 = .zero, .modify_flags = false, .output = .push, .command = .ipget };
2373 mem.writeIntLittle(u16, self.code.items[self.code.items.len - 8 ..][0..2], @bitCast(u16, push));
2374 mem.writeIntLittle(u16, self.code.items[self.code.items.len - 6 ..][0..2], @as(u16, 4));
2375 mem.writeIntLittle(u16, self.code.items[self.code.items.len - 4 ..][0..2], @bitCast(u16, instr));
2376 mem.writeIntLittle(u16, self.code.items[self.code.items.len - 2 ..][0..2], got_addr);
2377 switch (return_type.zigTypeTag()) {
2378 .Void => return MCValue{ .none = {} },
2379 .NoReturn => unreachable,
2380 else => return self.fail(inst.base.src, "TODO implement fn call with non-void return value", .{}),
2381 }
2382 }
2383 } else if (func_value.castTag(.extern_fn)) |_| {
2384 return self.fail(inst.base.src, "TODO implement calling extern functions", .{});
2385 } else {
2386 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});
2387 }
2388 } else {
2389 return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{});
2390 }
2391 },
2392 .arm, .armeb => {2349 .arm, .armeb => {
2393 for (info.args) |mc_arg, arg_i| {2350 for (info.args) |mc_arg, arg_i| {
2394 const arg = inst.args[arg_i];2351 const arg = inst.args[arg_i];
...@@ -2777,11 +2734,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2777,11 +2734,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2777 }2734 }
27782735
2779 fn genDbgStmt(self: *Self, inst: *ir.Inst.DbgStmt) !MCValue {2736 fn genDbgStmt(self: *Self, inst: *ir.Inst.DbgStmt) !MCValue {
2780 // TODO when reworking tzir memory layout, rework source locations here as2737 // TODO when reworking AIR memory layout, rework source locations here as
2781 // well to be more efficient, as well as support inlined function calls correctly.2738 // well to be more efficient, as well as support inlined function calls correctly.
2782 // For now we convert LazySrcLoc to absolute byte offset, to match what the2739 // For now we convert LazySrcLoc to absolute byte offset, to match what the
2783 // existing codegen code expects.2740 // existing codegen code expects.
2784 try self.dbgAdvancePCAndLine(inst.byte_offset);2741 try self.dbgAdvancePCAndLine(inst.line, inst.column);
2785 assert(inst.base.isUnused());2742 assert(inst.base.isUnused());
2786 return MCValue.dead;2743 return MCValue.dead;
2787 }2744 }
...@@ -3201,19 +3158,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -3201,19 +3158,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
3201 if (!inst.is_volatile and inst.base.isUnused())3158 if (!inst.is_volatile and inst.base.isUnused())
3202 return MCValue.dead;3159 return MCValue.dead;
3203 switch (arch) {3160 switch (arch) {
3204 .spu_2 => {
3205 if (inst.inputs.len > 0 or inst.output != null) {
3206 return self.fail(inst.base.src, "TODO implement inline asm inputs / outputs for SPU Mark II", .{});
3207 }
3208 if (mem.eql(u8, inst.asm_source, "undefined0")) {
3209 try self.code.resize(self.code.items.len + 2);
3210 var instr = Instruction{ .condition = .always, .input0 = .zero, .input1 = .zero, .modify_flags = false, .output = .discard, .command = .undefined0 };
3211 mem.writeIntLittle(u16, self.code.items[self.code.items.len - 2 ..][0..2], @bitCast(u16, instr));
3212 return MCValue.none;
3213 } else {
3214 return self.fail(inst.base.src, "TODO implement support for more SPU II assembly instructions", .{});
3215 }
3216 },
3217 .arm, .armeb => {3161 .arm, .armeb => {
3218 for (inst.inputs) |input, i| {3162 for (inst.inputs) |input, i| {
3219 if (input.len < 3 or input[0] != '{' or input[input.len - 1] != '}') {3163 if (input.len < 3 or input[0] != '{' or input[input.len - 1] != '}') {
...@@ -3235,7 +3179,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -3235,7 +3179,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
3235 return self.fail(inst.base.src, "TODO implement support for more arm assembly instructions", .{});3179 return self.fail(inst.base.src, "TODO implement support for more arm assembly instructions", .{});
3236 }3180 }
32373181
3238 if (inst.output_name) |output| {3182 if (inst.output_constraint) |output| {
3239 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {3183 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {
3240 return self.fail(inst.base.src, "unrecognized asm output constraint: '{s}'", .{output});3184 return self.fail(inst.base.src, "unrecognized asm output constraint: '{s}'", .{output});
3241 }3185 }
...@@ -3270,7 +3214,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -3270,7 +3214,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
3270 return self.fail(inst.base.src, "TODO implement support for more aarch64 assembly instructions", .{});3214 return self.fail(inst.base.src, "TODO implement support for more aarch64 assembly instructions", .{});
3271 }3215 }
32723216
3273 if (inst.output_name) |output| {3217 if (inst.output_constraint) |output| {
3274 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {3218 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {
3275 return self.fail(inst.base.src, "unrecognized asm output constraint: '{s}'", .{output});3219 return self.fail(inst.base.src, "unrecognized asm output constraint: '{s}'", .{output});
3276 }3220 }
...@@ -3303,7 +3247,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -3303,7 +3247,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
3303 return self.fail(inst.base.src, "TODO implement support for more riscv64 assembly instructions", .{});3247 return self.fail(inst.base.src, "TODO implement support for more riscv64 assembly instructions", .{});
3304 }3248 }
33053249
3306 if (inst.output_name) |output| {3250 if (inst.output_constraint) |output| {
3307 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {3251 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {
3308 return self.fail(inst.base.src, "unrecognized asm output constraint: '{s}'", .{output});3252 return self.fail(inst.base.src, "unrecognized asm output constraint: '{s}'", .{output});
3309 }3253 }
...@@ -3336,7 +3280,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -3336,7 +3280,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
3336 return self.fail(inst.base.src, "TODO implement support for more x86 assembly instructions", .{});3280 return self.fail(inst.base.src, "TODO implement support for more x86 assembly instructions", .{});
3337 }3281 }
33383282
3339 if (inst.output_name) |output| {3283 if (inst.output_constraint) |output| {
3340 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {3284 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {
3341 return self.fail(inst.base.src, "unrecognized asm output constraint: '{s}'", .{output});3285 return self.fail(inst.base.src, "unrecognized asm output constraint: '{s}'", .{output});
3342 }3286 }
...@@ -4528,7 +4472,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -4528,7 +4472,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
4528 .i386 => @import("codegen/x86.zig"),4472 .i386 => @import("codegen/x86.zig"),
4529 .x86_64 => @import("codegen/x86_64.zig"),4473 .x86_64 => @import("codegen/x86_64.zig"),
4530 .riscv64 => @import("codegen/riscv64.zig"),4474 .riscv64 => @import("codegen/riscv64.zig"),
4531 .spu_2 => @import("codegen/spu-mk2.zig"),
4532 .arm, .armeb => @import("codegen/arm.zig"),4475 .arm, .armeb => @import("codegen/arm.zig"),
4533 .aarch64, .aarch64_be, .aarch64_32 => @import("codegen/aarch64.zig"),4476 .aarch64, .aarch64_be, .aarch64_32 => @import("codegen/aarch64.zig"),
4534 else => struct {4477 else => struct {
src/codegen/c.zig+71-20
...@@ -30,6 +30,7 @@ pub const CValue = union(enum) {...@@ -30,6 +30,7 @@ pub const CValue = union(enum) {
30 arg: usize,30 arg: usize,
31 /// By-value31 /// By-value
32 decl: *Decl,32 decl: *Decl,
33 decl_ref: *Decl,
33};34};
3435
35pub const CValueMap = std.AutoHashMap(*Inst, CValue);36pub const CValueMap = std.AutoHashMap(*Inst, CValue);
...@@ -60,12 +61,13 @@ fn formatIdent(...@@ -60,12 +61,13 @@ fn formatIdent(
60 for (ident) |c, i| {61 for (ident) |c, i| {
61 switch (c) {62 switch (c) {
62 'a'...'z', 'A'...'Z', '_' => try writer.writeByte(c),63 'a'...'z', 'A'...'Z', '_' => try writer.writeByte(c),
64 '.' => try writer.writeByte('_'),
63 '0'...'9' => if (i == 0) {65 '0'...'9' => if (i == 0) {
64 try writer.print("${x:2}", .{c});66 try writer.print("_{x:2}", .{c});
65 } else {67 } else {
66 try writer.writeByte(c);68 try writer.writeByte(c);
67 },69 },
68 else => try writer.print("${x:2}", .{c}),70 else => try writer.print("_{x:2}", .{c}),
69 }71 }
70 }72 }
71}73}
...@@ -117,6 +119,7 @@ pub const Object = struct {...@@ -117,6 +119,7 @@ pub const Object = struct {
117 .constant => |inst| return o.dg.renderValue(w, inst.ty, inst.value().?),119 .constant => |inst| return o.dg.renderValue(w, inst.ty, inst.value().?),
118 .arg => |i| return w.print("a{d}", .{i}),120 .arg => |i| return w.print("a{d}", .{i}),
119 .decl => |decl| return w.writeAll(mem.span(decl.name)),121 .decl => |decl| return w.writeAll(mem.span(decl.name)),
122 .decl_ref => |decl| return w.print("&{s}", .{decl.name}),
120 }123 }
121 }124 }
122125
...@@ -190,8 +193,8 @@ pub const DeclGen = struct {...@@ -190,8 +193,8 @@ pub const DeclGen = struct {
190 const decl = val.castTag(.decl_ref).?.data;193 const decl = val.castTag(.decl_ref).?.data;
191194
192 // Determine if we must pointer cast.195 // Determine if we must pointer cast.
193 const decl_tv = decl.typed_value.most_recent.typed_value;196 assert(decl.has_tv);
194 if (t.eql(decl_tv.ty)) {197 if (t.eql(decl.ty)) {
195 try writer.print("&{s}", .{decl.name});198 try writer.print("&{s}", .{decl.name});
196 } else {199 } else {
197 try writer.writeAll("(");200 try writer.writeAll("(");
...@@ -326,12 +329,11 @@ pub const DeclGen = struct {...@@ -326,12 +329,11 @@ pub const DeclGen = struct {
326 if (!is_global) {329 if (!is_global) {
327 try w.writeAll("static ");330 try w.writeAll("static ");
328 }331 }
329 const tv = dg.decl.typed_value.most_recent.typed_value;332 try dg.renderType(w, dg.decl.ty.fnReturnType());
330 try dg.renderType(w, tv.ty.fnReturnType());
331 const decl_name = mem.span(dg.decl.name);333 const decl_name = mem.span(dg.decl.name);
332 try w.print(" {s}(", .{decl_name});334 try w.print(" {s}(", .{decl_name});
333 const param_len = tv.ty.fnParamLen();335 const param_len = dg.decl.ty.fnParamLen();
334 const is_var_args = tv.ty.fnIsVarArgs();336 const is_var_args = dg.decl.ty.fnIsVarArgs();
335 if (param_len == 0 and !is_var_args)337 if (param_len == 0 and !is_var_args)
336 try w.writeAll("void")338 try w.writeAll("void")
337 else {339 else {
...@@ -340,7 +342,7 @@ pub const DeclGen = struct {...@@ -340,7 +342,7 @@ pub const DeclGen = struct {
340 if (index > 0) {342 if (index > 0) {
341 try w.writeAll(", ");343 try w.writeAll(", ");
342 }344 }
343 try dg.renderType(w, tv.ty.fnParamType(index));345 try dg.renderType(w, dg.decl.ty.fnParamType(index));
344 try w.print(" a{d}", .{index});346 try w.print(" a{d}", .{index});
345 }347 }
346 }348 }
...@@ -529,13 +531,17 @@ pub const DeclGen = struct {...@@ -529,13 +531,17 @@ pub const DeclGen = struct {
529 }531 }
530 }532 }
531533
532 fn functionIsGlobal(dg: *DeclGen, tv: TypedValue) bool {534 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
533 switch (tv.val.tag()) {535 switch (tv.val.tag()) {
534 .extern_fn => return true,536 .extern_fn => return true,
535 .function => {537 .function => {
536 const func = tv.val.castTag(.function).?.data;538 const func = tv.val.castTag(.function).?.data;
537 return dg.module.decl_exports.contains(func.owner_decl);539 return dg.module.decl_exports.contains(func.owner_decl);
538 },540 },
541 .variable => {
542 const variable = tv.val.castTag(.variable).?.data;
543 return dg.module.decl_exports.contains(variable.owner_decl);
544 },
539 else => unreachable,545 else => unreachable,
540 }546 }
541 }547 }
...@@ -545,10 +551,12 @@ pub fn genDecl(o: *Object) !void {...@@ -545,10 +551,12 @@ pub fn genDecl(o: *Object) !void {
545 const tracy = trace(@src());551 const tracy = trace(@src());
546 defer tracy.end();552 defer tracy.end();
547553
548 const tv = o.dg.decl.typed_value.most_recent.typed_value;554 const tv: TypedValue = .{
549555 .ty = o.dg.decl.ty,
556 .val = o.dg.decl.val,
557 };
550 if (tv.val.castTag(.function)) |func_payload| {558 if (tv.val.castTag(.function)) |func_payload| {
551 const is_global = o.dg.functionIsGlobal(tv);559 const is_global = o.dg.declIsGlobal(tv);
552 const fwd_decl_writer = o.dg.fwd_decl.writer();560 const fwd_decl_writer = o.dg.fwd_decl.writer();
553 if (is_global) {561 if (is_global) {
554 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");562 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
...@@ -569,6 +577,29 @@ pub fn genDecl(o: *Object) !void {...@@ -569,6 +577,29 @@ pub fn genDecl(o: *Object) !void {
569 try writer.writeAll("ZIG_EXTERN_C ");577 try writer.writeAll("ZIG_EXTERN_C ");
570 try o.dg.renderFunctionSignature(writer, true);578 try o.dg.renderFunctionSignature(writer, true);
571 try writer.writeAll(";\n");579 try writer.writeAll(";\n");
580 } else if (tv.val.castTag(.variable)) |var_payload| {
581 const variable: *Module.Var = var_payload.data;
582 const is_global = o.dg.declIsGlobal(tv);
583 const fwd_decl_writer = o.dg.fwd_decl.writer();
584 if (is_global or variable.is_extern) {
585 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
586 }
587 if (variable.is_threadlocal) {
588 try fwd_decl_writer.writeAll("zig_threadlocal ");
589 }
590 try o.dg.renderType(fwd_decl_writer, o.dg.decl.ty);
591 const decl_name = mem.span(o.dg.decl.name);
592 try fwd_decl_writer.print(" {s};\n", .{decl_name});
593
594 try o.indent_writer.insertNewline();
595 const w = o.writer();
596 try o.dg.renderType(w, o.dg.decl.ty);
597 try w.print(" {s} = ", .{decl_name});
598 if (variable.init.tag() != .unreachable_value) {
599 try o.dg.renderValue(w, tv.ty, variable.init);
600 }
601 try w.writeAll(";");
602 try o.indent_writer.insertNewline();
572 } else {603 } else {
573 const writer = o.writer();604 const writer = o.writer();
574 try writer.writeAll("static ");605 try writer.writeAll("static ");
...@@ -589,12 +620,15 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {...@@ -589,12 +620,15 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
589 const tracy = trace(@src());620 const tracy = trace(@src());
590 defer tracy.end();621 defer tracy.end();
591622
592 const tv = dg.decl.typed_value.most_recent.typed_value;623 const tv: TypedValue = .{
624 .ty = dg.decl.ty,
625 .val = dg.decl.val,
626 };
593 const writer = dg.fwd_decl.writer();627 const writer = dg.fwd_decl.writer();
594628
595 switch (tv.ty.zigTypeTag()) {629 switch (tv.ty.zigTypeTag()) {
596 .Fn => {630 .Fn => {
597 const is_global = dg.functionIsGlobal(tv);631 const is_global = dg.declIsGlobal(tv);
598 if (is_global) {632 if (is_global) {
599 try writer.writeAll("ZIG_EXTERN_C ");633 try writer.writeAll("ZIG_EXTERN_C ");
600 }634 }
...@@ -692,7 +726,7 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi...@@ -692,7 +726,7 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
692 .wrap_errunion_err => try genWrapErrUnionErr(o, inst.castTag(.wrap_errunion_err).?),726 .wrap_errunion_err => try genWrapErrUnionErr(o, inst.castTag(.wrap_errunion_err).?),
693 .br_block_flat => return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for br_block_flat", .{}),727 .br_block_flat => return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for br_block_flat", .{}),
694 .ptrtoint => return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for ptrtoint", .{}),728 .ptrtoint => return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for ptrtoint", .{}),
695 .varptr => return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for varptr", .{}),729 .varptr => try genVarPtr(o, inst.castTag(.varptr).?),
696 .floatcast => return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for floatcast", .{}),730 .floatcast => return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for floatcast", .{}),
697 };731 };
698 switch (result_value) {732 switch (result_value) {
...@@ -705,6 +739,10 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi...@@ -705,6 +739,10 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
705 try writer.writeAll("}");739 try writer.writeAll("}");
706}740}
707741
742fn genVarPtr(o: *Object, inst: *Inst.VarPtr) !CValue {
743 return CValue{ .decl_ref = inst.variable.owner_decl };
744}
745
708fn genAlloc(o: *Object, alloc: *Inst.NoOp) !CValue {746fn genAlloc(o: *Object, alloc: *Inst.NoOp) !CValue {
709 const writer = o.writer();747 const writer = o.writer();
710748
...@@ -739,6 +777,12 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {...@@ -739,6 +777,12 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {
739 try o.writeCValue(writer, wrapped);777 try o.writeCValue(writer, wrapped);
740 try writer.writeAll(";\n");778 try writer.writeAll(";\n");
741 },779 },
780 .decl_ref => |decl| {
781 const wrapped: CValue = .{ .decl = decl };
782 try writer.writeAll(" = ");
783 try o.writeCValue(writer, wrapped);
784 try writer.writeAll(";\n");
785 },
742 else => {786 else => {
743 try writer.writeAll(" = *");787 try writer.writeAll(" = *");
744 try o.writeCValue(writer, operand);788 try o.writeCValue(writer, operand);
...@@ -787,6 +831,13 @@ fn genStore(o: *Object, inst: *Inst.BinOp) !CValue {...@@ -787,6 +831,13 @@ fn genStore(o: *Object, inst: *Inst.BinOp) !CValue {
787 try o.writeCValue(writer, src_val);831 try o.writeCValue(writer, src_val);
788 try writer.writeAll(";\n");832 try writer.writeAll(";\n");
789 },833 },
834 .decl_ref => |decl| {
835 const dest: CValue = .{ .decl = decl };
836 try o.writeCValue(writer, dest);
837 try writer.writeAll(" = ");
838 try o.writeCValue(writer, src_val);
839 try writer.writeAll(";\n");
840 },
790 else => {841 else => {
791 try writer.writeAll("*");842 try writer.writeAll("*");
792 try o.writeCValue(writer, dest_ptr);843 try o.writeCValue(writer, dest_ptr);
...@@ -842,7 +893,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {...@@ -842,7 +893,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {
842 else893 else
843 unreachable;894 unreachable;
844895
845 const fn_ty = fn_decl.typed_value.most_recent.typed_value.ty;896 const fn_ty = fn_decl.ty;
846 const ret_ty = fn_ty.fnReturnType();897 const ret_ty = fn_ty.fnReturnType();
847 const unused_result = inst.base.isUnused();898 const unused_result = inst.base.isUnused();
848 var result_local: CValue = .none;899 var result_local: CValue = .none;
...@@ -1036,11 +1087,11 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {...@@ -1036,11 +1087,11 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
1036 }1087 }
1037 const volatile_string: []const u8 = if (as.is_volatile) "volatile " else "";1088 const volatile_string: []const u8 = if (as.is_volatile) "volatile " else "";
1038 try writer.print("__asm {s}(\"{s}\"", .{ volatile_string, as.asm_source });1089 try writer.print("__asm {s}(\"{s}\"", .{ volatile_string, as.asm_source });
1039 if (as.output) |_| {1090 if (as.output_constraint) |_| {
1040 return o.dg.fail(.{ .node_offset = 0 }, "TODO inline asm output", .{});1091 return o.dg.fail(.{ .node_offset = 0 }, "TODO: CBE inline asm output", .{});
1041 }1092 }
1042 if (as.inputs.len > 0) {1093 if (as.inputs.len > 0) {
1043 if (as.output == null) {1094 if (as.output_constraint == null) {
1044 try writer.writeAll(" :");1095 try writer.writeAll(" :");
1045 }1096 }
1046 try writer.writeAll(": ");1097 try writer.writeAll(": ");
src/codegen/llvm.zig+35-17
...@@ -193,14 +193,9 @@ pub const Object = struct {...@@ -193,14 +193,9 @@ pub const Object = struct {
193 try stderr.print(193 try stderr.print(
194 \\Zig is expecting LLVM to understand this target: '{s}'194 \\Zig is expecting LLVM to understand this target: '{s}'
195 \\However LLVM responded with: "{s}"195 \\However LLVM responded with: "{s}"
196 \\Zig is unable to continue. This is a bug in Zig:
197 \\https://github.com/ziglang/zig/issues/438
198 \\196 \\
199 ,197 ,
200 .{198 .{ llvm_target_triple, error_message },
201 llvm_target_triple,
202 error_message,
203 },
204 );199 );
205 return error.InvalidLLVMTriple;200 return error.InvalidLLVMTriple;
206 }201 }
...@@ -325,17 +320,17 @@ pub const DeclGen = struct {...@@ -325,17 +320,17 @@ pub const DeclGen = struct {
325320
326 fn genDecl(self: *DeclGen) !void {321 fn genDecl(self: *DeclGen) !void {
327 const decl = self.decl;322 const decl = self.decl;
328 const typed_value = decl.typed_value.most_recent.typed_value;323 assert(decl.has_tv);
329324
330 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, typed_value.ty, typed_value.val });325 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val });
331326
332 if (typed_value.val.castTag(.function)) |func_payload| {327 if (decl.val.castTag(.function)) |func_payload| {
333 const func = func_payload.data;328 const func = func_payload.data;
334329
335 const llvm_func = try self.resolveLLVMFunction(func.owner_decl);330 const llvm_func = try self.resolveLLVMFunction(func.owner_decl);
336331
337 // This gets the LLVM values from the function and stores them in `self.args`.332 // This gets the LLVM values from the function and stores them in `self.args`.
338 const fn_param_len = func.owner_decl.typed_value.most_recent.typed_value.ty.fnParamLen();333 const fn_param_len = func.owner_decl.ty.fnParamLen();
339 var args = try self.gpa.alloc(*const llvm.Value, fn_param_len);334 var args = try self.gpa.alloc(*const llvm.Value, fn_param_len);
340335
341 for (args) |*arg, i| {336 for (args) |*arg, i| {
...@@ -368,7 +363,7 @@ pub const DeclGen = struct {...@@ -368,7 +363,7 @@ pub const DeclGen = struct {
368 defer fg.deinit();363 defer fg.deinit();
369364
370 try fg.genBody(func.body);365 try fg.genBody(func.body);
371 } else if (typed_value.val.castTag(.extern_fn)) |extern_fn| {366 } else if (decl.val.castTag(.extern_fn)) |extern_fn| {
372 _ = try self.resolveLLVMFunction(extern_fn.data);367 _ = try self.resolveLLVMFunction(extern_fn.data);
373 } else {368 } else {
374 _ = try self.resolveGlobalDecl(decl);369 _ = try self.resolveGlobalDecl(decl);
...@@ -380,7 +375,8 @@ pub const DeclGen = struct {...@@ -380,7 +375,8 @@ pub const DeclGen = struct {
380 // TODO: do we want to store this in our own datastructure?375 // TODO: do we want to store this in our own datastructure?
381 if (self.llvmModule().getNamedFunction(func.name)) |llvm_fn| return llvm_fn;376 if (self.llvmModule().getNamedFunction(func.name)) |llvm_fn| return llvm_fn;
382377
383 const zig_fn_type = func.typed_value.most_recent.typed_value.ty;378 assert(func.has_tv);
379 const zig_fn_type = func.ty;
384 const return_type = zig_fn_type.fnReturnType();380 const return_type = zig_fn_type.fnReturnType();
385381
386 const fn_param_len = zig_fn_type.fnParamLen();382 const fn_param_len = zig_fn_type.fnParamLen();
...@@ -415,11 +411,11 @@ pub const DeclGen = struct {...@@ -415,11 +411,11 @@ pub const DeclGen = struct {
415 // TODO: do we want to store this in our own datastructure?411 // TODO: do we want to store this in our own datastructure?
416 if (self.llvmModule().getNamedGlobal(decl.name)) |val| return val;412 if (self.llvmModule().getNamedGlobal(decl.name)) |val| return val;
417413
418 const typed_value = decl.typed_value.most_recent.typed_value;414 assert(decl.has_tv);
419415
420 // TODO: remove this redundant `getLLVMType`, it is also called in `genTypedValue`.416 // TODO: remove this redundant `getLLVMType`, it is also called in `genTypedValue`.
421 const llvm_type = try self.getLLVMType(typed_value.ty);417 const llvm_type = try self.getLLVMType(decl.ty);
422 const val = try self.genTypedValue(typed_value, null);418 const val = try self.genTypedValue(.{ .ty = decl.ty, .val = decl.val }, null);
423 const global = self.llvmModule().addGlobal(llvm_type, decl.name);419 const global = self.llvmModule().addGlobal(llvm_type, decl.name);
424 llvm.setInitializer(global, val);420 llvm.setInitializer(global, val);
425421
...@@ -430,6 +426,7 @@ pub const DeclGen = struct {...@@ -430,6 +426,7 @@ pub const DeclGen = struct {
430 }426 }
431427
432 fn getLLVMType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type {428 fn getLLVMType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type {
429 log.debug("getLLVMType for {}", .{t});
433 switch (t.zigTypeTag()) {430 switch (t.zigTypeTag()) {
434 .Void => return self.context().voidType(),431 .Void => return self.context().voidType(),
435 .NoReturn => return self.context().voidType(),432 .NoReturn => return self.context().voidType(),
...@@ -464,7 +461,27 @@ pub const DeclGen = struct {...@@ -464,7 +461,27 @@ pub const DeclGen = struct {
464 return self.todo("implement optional pointers as actual pointers", .{});461 return self.todo("implement optional pointers as actual pointers", .{});
465 }462 }
466 },463 },
467 else => return self.todo("implement getLLVMType for type '{}'", .{t}),464 .ComptimeInt => unreachable,
465 .ComptimeFloat => unreachable,
466 .Type => unreachable,
467 .Undefined => unreachable,
468 .Null => unreachable,
469 .EnumLiteral => unreachable,
470
471 .BoundFn => @panic("TODO remove BoundFn from the language"),
472
473 .Float,
474 .Struct,
475 .ErrorUnion,
476 .ErrorSet,
477 .Enum,
478 .Union,
479 .Fn,
480 .Opaque,
481 .Frame,
482 .AnyFrame,
483 .Vector,
484 => return self.todo("implement getLLVMType for type '{}'", .{t}),
468 }485 }
469 }486 }
470487
...@@ -688,7 +705,8 @@ pub const FuncGen = struct {...@@ -688,7 +705,8 @@ pub const FuncGen = struct {
688 else705 else
689 unreachable;706 unreachable;
690707
691 const zig_fn_type = fn_decl.typed_value.most_recent.typed_value.ty;708 assert(fn_decl.has_tv);
709 const zig_fn_type = fn_decl.ty;
692 const llvm_fn = try self.dg.resolveLLVMFunction(fn_decl);710 const llvm_fn = try self.dg.resolveLLVMFunction(fn_decl);
693711
694 const num_args = inst.args.len;712 const num_args = inst.args.len;
src/codegen/spirv.zig+37-53
...@@ -71,10 +71,7 @@ pub const DeclGen = struct {...@@ -71,10 +71,7 @@ pub const DeclGen = struct {
71 decl: *Decl,71 decl: *Decl,
72 error_msg: ?*Module.ErrorMsg,72 error_msg: ?*Module.ErrorMsg,
7373
74 const Error = error{74 const Error = error{ AnalysisFail, OutOfMemory };
75 AnalysisFail,
76 OutOfMemory
77 };
7875
79 /// This structure is used to return information about a type typically used for arithmetic operations.76 /// This structure is used to return information about a type typically used for arithmetic operations.
80 /// These types may either be integers, floats, or a vector of these. Most scalar operations also work on vectors,77 /// These types may either be integers, floats, or a vector of these. Most scalar operations also work on vectors,
...@@ -153,7 +150,7 @@ pub const DeclGen = struct {...@@ -153,7 +150,7 @@ pub const DeclGen = struct {
153150
154 // 8, 16 and 64-bit integers require the Int8, Int16 and Inr64 capabilities respectively.151 // 8, 16 and 64-bit integers require the Int8, Int16 and Inr64 capabilities respectively.
155 // 32-bit integers are always supported (see spec, 2.16.1, Data rules).152 // 32-bit integers are always supported (see spec, 2.16.1, Data rules).
156 const ints = [_]struct{ bits: u16, feature: ?Target.spirv.Feature } {153 const ints = [_]struct { bits: u16, feature: ?Target.spirv.Feature }{
157 .{ .bits = 8, .feature = .Int8 },154 .{ .bits = 8, .feature = .Int8 },
158 .{ .bits = 16, .feature = .Int16 },155 .{ .bits = 16, .feature = .Int16 },
159 .{ .bits = 32, .feature = null },156 .{ .bits = 32, .feature = null },
...@@ -215,23 +212,18 @@ pub const DeclGen = struct {...@@ -215,23 +212,18 @@ pub const DeclGen = struct {
215 const int_info = ty.intInfo(target);212 const int_info = ty.intInfo(target);
216 // TODO: Maybe it's useful to also return this value.213 // TODO: Maybe it's useful to also return this value.
217 const maybe_backing_bits = self.backingIntBits(int_info.bits);214 const maybe_backing_bits = self.backingIntBits(int_info.bits);
218 break :blk ArithmeticTypeInfo{215 break :blk ArithmeticTypeInfo{ .bits = int_info.bits, .is_vector = false, .signedness = int_info.signedness, .class = if (maybe_backing_bits) |backing_bits|
219 .bits = int_info.bits,216 if (backing_bits == int_info.bits)
220 .is_vector = false,217 ArithmeticTypeInfo.Class.integer
221 .signedness = int_info.signedness,218 else
222 .class = if (maybe_backing_bits) |backing_bits|219 ArithmeticTypeInfo.Class.strange_integer
223 if (backing_bits == int_info.bits)220 else
224 ArithmeticTypeInfo.Class.integer221 .composite_integer };
225 else
226 ArithmeticTypeInfo.Class.strange_integer
227 else
228 .composite_integer
229 };
230 },222 },
231 // As of yet, there is no vector support in the self-hosted compiler.223 // As of yet, there is no vector support in the self-hosted compiler.
232 .Vector => self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement arithmeticTypeInfo for Vector", .{}),224 .Vector => self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: implement arithmeticTypeInfo for Vector", .{}),
233 // TODO: For which types is this the case?225 // TODO: For which types is this the case?
234 else => self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement arithmeticTypeInfo for {}", .{ty}),226 else => self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: implement arithmeticTypeInfo for {}", .{ty}),
235 };227 };
236 }228 }
237229
...@@ -259,16 +251,8 @@ pub const DeclGen = struct {...@@ -259,16 +251,8 @@ pub const DeclGen = struct {
259 // f16 and f32 require one word of storage. f64 requires 2, low-order first.251 // f16 and f32 require one word of storage. f64 requires 2, low-order first.
260252
261 switch (val.tag()) {253 switch (val.tag()) {
262 .float_16 => try writeInstruction(code, .OpConstant, &[_]u32{254 .float_16 => try writeInstruction(code, .OpConstant, &[_]u32{ result_type_id, result_id, @bitCast(u16, val.castTag(.float_16).?.data) }),
263 result_type_id,255 .float_32 => try writeInstruction(code, .OpConstant, &[_]u32{ result_type_id, result_id, @bitCast(u32, val.castTag(.float_32).?.data) }),
264 result_id,
265 @bitCast(u16, val.castTag(.float_16).?.data)
266 }),
267 .float_32 => try writeInstruction(code, .OpConstant, &[_]u32{
268 result_type_id,
269 result_id,
270 @bitCast(u32, val.castTag(.float_32).?.data)
271 }),
272 .float_64 => {256 .float_64 => {
273 const float_bits = @bitCast(u64, val.castTag(.float_64).?.data);257 const float_bits = @bitCast(u64, val.castTag(.float_64).?.data);
274 try writeInstruction(code, .OpConstant, &[_]u32{258 try writeInstruction(code, .OpConstant, &[_]u32{
...@@ -280,10 +264,10 @@ pub const DeclGen = struct {...@@ -280,10 +264,10 @@ pub const DeclGen = struct {
280 },264 },
281 .float_128 => unreachable, // Filtered out in the call to getOrGenType.265 .float_128 => unreachable, // Filtered out in the call to getOrGenType.
282 // TODO: What tags do we need to handle here anyway?266 // TODO: What tags do we need to handle here anyway?
283 else => return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: float constant generation of value {s}\n", .{ val.tag() }),267 else => return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: float constant generation of value {s}\n", .{val.tag()}),
284 }268 }
285 },269 },
286 else => return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: constant generation of type {s}\n", .{ ty.zigTypeTag() }),270 else => return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: constant generation of type {s}\n", .{ty.zigTypeTag()}),
287 }271 }
288272
289 return result_id;273 return result_id;
...@@ -300,13 +284,13 @@ pub const DeclGen = struct {...@@ -300,13 +284,13 @@ pub const DeclGen = struct {
300 const result_id = self.spv.allocResultId();284 const result_id = self.spv.allocResultId();
301285
302 switch (ty.zigTypeTag()) {286 switch (ty.zigTypeTag()) {
303 .Void => try writeInstruction(code, .OpTypeVoid, &[_]u32{ result_id }),287 .Void => try writeInstruction(code, .OpTypeVoid, &[_]u32{result_id}),
304 .Bool => try writeInstruction(code, .OpTypeBool, &[_]u32{ result_id }),288 .Bool => try writeInstruction(code, .OpTypeBool, &[_]u32{result_id}),
305 .Int => {289 .Int => {
306 const int_info = ty.intInfo(target);290 const int_info = ty.intInfo(target);
307 const backing_bits = self.backingIntBits(int_info.bits) orelse {291 const backing_bits = self.backingIntBits(int_info.bits) orelse {
308 // Integers too big for any native type are represented as "composite integers": An array of largestSupportedIntBits.292 // Integers too big for any native type are represented as "composite integers": An array of largestSupportedIntBits.
309 return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement composite ints {}", .{ ty });293 return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: implement composite ints {}", .{ty});
310 };294 };
311295
312 // TODO: If backing_bits != int_info.bits, a duplicate type might be generated here.296 // TODO: If backing_bits != int_info.bits, a duplicate type might be generated here.
...@@ -332,7 +316,7 @@ pub const DeclGen = struct {...@@ -332,7 +316,7 @@ pub const DeclGen = struct {
332 };316 };
333317
334 if (!supported) {318 if (!supported) {
335 return self.fail(.{.node_offset = 0}, "Floating point width of {} bits is not supported for the current SPIR-V feature set", .{ bits });319 return self.fail(.{ .node_offset = 0 }, "Floating point width of {} bits is not supported for the current SPIR-V feature set", .{bits});
336 }320 }
337321
338 try writeInstruction(code, .OpTypeFloat, &[_]u32{ result_id, bits });322 try writeInstruction(code, .OpTypeFloat, &[_]u32{ result_id, bits });
...@@ -340,9 +324,9 @@ pub const DeclGen = struct {...@@ -340,9 +324,9 @@ pub const DeclGen = struct {
340 .Fn => {324 .Fn => {
341 // We only support zig-calling-convention functions, no varargs.325 // We only support zig-calling-convention functions, no varargs.
342 if (ty.fnCallingConvention() != .Unspecified)326 if (ty.fnCallingConvention() != .Unspecified)
343 return self.fail(.{.node_offset = 0}, "Unsupported calling convention for SPIR-V", .{});327 return self.fail(.{ .node_offset = 0 }, "Unsupported calling convention for SPIR-V", .{});
344 if (ty.fnIsVarArgs())328 if (ty.fnIsVarArgs())
345 return self.fail(.{.node_offset = 0}, "VarArgs unsupported for SPIR-V", .{});329 return self.fail(.{ .node_offset = 0 }, "VarArgs unsupported for SPIR-V", .{});
346330
347 // In order to avoid a temporary here, first generate all the required types and then simply look them up331 // In order to avoid a temporary here, first generate all the required types and then simply look them up
348 // when generating the function type.332 // when generating the function type.
...@@ -355,7 +339,7 @@ pub const DeclGen = struct {...@@ -355,7 +339,7 @@ pub const DeclGen = struct {
355 const return_type_id = try self.getOrGenType(ty.fnReturnType());339 const return_type_id = try self.getOrGenType(ty.fnReturnType());
356340
357 // result id + result type id + parameter type ids.341 // result id + result type id + parameter type ids.
358 try writeOpcode(code, .OpTypeFunction, 2 + @intCast(u32, ty.fnParamLen()) );342 try writeOpcode(code, .OpTypeFunction, 2 + @intCast(u32, ty.fnParamLen()));
359 try code.appendSlice(&.{ result_id, return_type_id });343 try code.appendSlice(&.{ result_id, return_type_id });
360344
361 i = 0;345 i = 0;
...@@ -373,7 +357,7 @@ pub const DeclGen = struct {...@@ -373,7 +357,7 @@ pub const DeclGen = struct {
373 // is adequate at all for this.357 // is adequate at all for this.
374358
375 // TODO: Vectors are not yet supported by the self-hosted compiler itself it seems.359 // TODO: Vectors are not yet supported by the self-hosted compiler itself it seems.
376 return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement type Vector", .{});360 return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: implement type Vector", .{});
377 },361 },
378 .Null,362 .Null,
379 .Undefined,363 .Undefined,
...@@ -385,7 +369,7 @@ pub const DeclGen = struct {...@@ -385,7 +369,7 @@ pub const DeclGen = struct {
385369
386 .BoundFn => unreachable, // this type will be deleted from the language.370 .BoundFn => unreachable, // this type will be deleted from the language.
387371
388 else => |tag| return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement type {}s", .{ tag }),372 else => |tag| return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: implement type {}s", .{tag}),
389 }373 }
390374
391 try self.types.putNoClobber(ty, result_id);375 try self.types.putNoClobber(ty, result_id);
...@@ -393,25 +377,25 @@ pub const DeclGen = struct {...@@ -393,25 +377,25 @@ pub const DeclGen = struct {
393 }377 }
394378
395 pub fn gen(self: *DeclGen) !void {379 pub fn gen(self: *DeclGen) !void {
396 const result_id = self.decl.fn_link.spirv.id;380 const decl = self.decl;
397 const tv = self.decl.typed_value.most_recent.typed_value;381 const result_id = decl.fn_link.spirv.id;
398382
399 if (tv.val.castTag(.function)) |func_payload| {383 if (decl.val.castTag(.function)) |func_payload| {
400 std.debug.assert(tv.ty.zigTypeTag() == .Fn);384 std.debug.assert(decl.ty.zigTypeTag() == .Fn);
401 const prototype_id = try self.getOrGenType(tv.ty);385 const prototype_id = try self.getOrGenType(decl.ty);
402 try writeInstruction(&self.spv.fn_decls, .OpFunction, &[_]u32{386 try writeInstruction(&self.spv.fn_decls, .OpFunction, &[_]u32{
403 self.types.get(tv.ty.fnReturnType()).?, // This type should be generated along with the prototype.387 self.types.get(decl.ty.fnReturnType()).?, // This type should be generated along with the prototype.
404 result_id,388 result_id,
405 @bitCast(u32, spec.FunctionControl{}), // TODO: We can set inline here if the type requires it.389 @bitCast(u32, spec.FunctionControl{}), // TODO: We can set inline here if the type requires it.
406 prototype_id,390 prototype_id,
407 });391 });
408392
409 const params = tv.ty.fnParamLen();393 const params = decl.ty.fnParamLen();
410 var i: usize = 0;394 var i: usize = 0;
411395
412 try self.args.ensureCapacity(params);396 try self.args.ensureCapacity(params);
413 while (i < params) : (i += 1) {397 while (i < params) : (i += 1) {
414 const param_type_id = self.types.get(tv.ty.fnParamType(i)).?;398 const param_type_id = self.types.get(decl.ty.fnParamType(i)).?;
415 const arg_result_id = self.spv.allocResultId();399 const arg_result_id = self.spv.allocResultId();
416 try writeInstruction(&self.spv.fn_decls, .OpFunctionParameter, &[_]u32{ param_type_id, arg_result_id });400 try writeInstruction(&self.spv.fn_decls, .OpFunctionParameter, &[_]u32{ param_type_id, arg_result_id });
417 self.args.appendAssumeCapacity(arg_result_id);401 self.args.appendAssumeCapacity(arg_result_id);
...@@ -424,7 +408,7 @@ pub const DeclGen = struct {...@@ -424,7 +408,7 @@ pub const DeclGen = struct {
424408
425 try writeInstruction(&self.spv.fn_decls, .OpFunctionEnd, &[_]u32{});409 try writeInstruction(&self.spv.fn_decls, .OpFunctionEnd, &[_]u32{});
426 } else {410 } else {
427 return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: generate decl type {}", .{ tv.ty.zigTypeTag() });411 return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: generate decl type {}", .{decl.ty.zigTypeTag()});
428 }412 }
429 }413 }
430414
...@@ -462,7 +446,7 @@ pub const DeclGen = struct {...@@ -462,7 +446,7 @@ pub const DeclGen = struct {
462 .ret => self.genRet(inst.castTag(.ret).?),446 .ret => self.genRet(inst.castTag(.ret).?),
463 .retvoid => self.genRetVoid(),447 .retvoid => self.genRetVoid(),
464 .unreach => self.genUnreach(),448 .unreach => self.genUnreach(),
465 else => self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement inst {}", .{inst.tag}),449 else => self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: implement inst {}", .{inst.tag}),
466 };450 };
467 }451 }
468452
...@@ -486,7 +470,7 @@ pub const DeclGen = struct {...@@ -486,7 +470,7 @@ pub const DeclGen = struct {
486 const info = try self.arithmeticTypeInfo(inst.lhs.ty);470 const info = try self.arithmeticTypeInfo(inst.lhs.ty);
487471
488 if (info.class == .composite_integer)472 if (info.class == .composite_integer)
489 return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: binary operations for composite integers", .{});473 return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: binary operations for composite integers", .{});
490474
491 const is_bool = info.class == .bool;475 const is_bool = info.class == .bool;
492 const is_float = info.class == .float;476 const is_float = info.class == .float;
...@@ -533,7 +517,7 @@ pub const DeclGen = struct {...@@ -533,7 +517,7 @@ pub const DeclGen = struct {
533 if (info.class != .strange_integer)517 if (info.class != .strange_integer)
534 return result_id;518 return result_id;
535519
536 return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: strange integer operation mask", .{});520 return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: strange integer operation mask", .{});
537 }521 }
538522
539 fn genUnOp(self: *DeclGen, inst: *Inst.UnOp) !u32 {523 fn genUnOp(self: *DeclGen, inst: *Inst.UnOp) !u32 {
...@@ -563,7 +547,7 @@ pub const DeclGen = struct {...@@ -563,7 +547,7 @@ pub const DeclGen = struct {
563 fn genRet(self: *DeclGen, inst: *Inst.UnOp) !?u32 {547 fn genRet(self: *DeclGen, inst: *Inst.UnOp) !?u32 {
564 const operand_id = try self.resolve(inst.operand);548 const operand_id = try self.resolve(inst.operand);
565 // TODO: This instruction needs to be the last in a block. Is that guaranteed?549 // TODO: This instruction needs to be the last in a block. Is that guaranteed?
566 try writeInstruction(&self.spv.fn_decls, .OpReturnValue, &[_]u32{ operand_id });550 try writeInstruction(&self.spv.fn_decls, .OpReturnValue, &[_]u32{operand_id});
567 return null;551 return null;
568 }552 }
569553
src/codegen/spirv/spec.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1//! This file is auto-generated by tools/gen_spirv_spec.zig.1//! This file is auto-generated by tools/gen_spirv_spec.zig.
22
3const Version = @import("builtin").Version;3const Version = @import("std").builtin.Version;
4pub const version = Version{ .major = 1, .minor = 5, .patch = 4 };4pub const version = Version{ .major = 1, .minor = 5, .patch = 4 };
5pub const magic_number: u32 = 0x07230203;5pub const magic_number: u32 = 0x07230203;
6pub const Opcode = extern enum(u16) {6pub const Opcode = extern enum(u16) {
src/codegen/spu-mk2.zig deleted-170
...@@ -1,170 +0,0 @@
1const std = @import("std");
2
3pub const Interpreter = @import("spu-mk2/interpreter.zig").Interpreter;
4
5pub const ExecutionCondition = enum(u3) {
6 always = 0,
7 when_zero = 1,
8 not_zero = 2,
9 greater_zero = 3,
10 less_than_zero = 4,
11 greater_or_equal_zero = 5,
12 less_or_equal_zero = 6,
13 overflow = 7,
14};
15
16pub const InputBehaviour = enum(u2) {
17 zero = 0,
18 immediate = 1,
19 peek = 2,
20 pop = 3,
21};
22
23pub const OutputBehaviour = enum(u2) {
24 discard = 0,
25 push = 1,
26 jump = 2,
27 jump_relative = 3,
28};
29
30pub const Command = enum(u5) {
31 copy = 0,
32 ipget = 1,
33 get = 2,
34 set = 3,
35 store8 = 4,
36 store16 = 5,
37 load8 = 6,
38 load16 = 7,
39 undefined0 = 8,
40 undefined1 = 9,
41 frget = 10,
42 frset = 11,
43 bpget = 12,
44 bpset = 13,
45 spget = 14,
46 spset = 15,
47 add = 16,
48 sub = 17,
49 mul = 18,
50 div = 19,
51 mod = 20,
52 @"and" = 21,
53 @"or" = 22,
54 xor = 23,
55 not = 24,
56 signext = 25,
57 rol = 26,
58 ror = 27,
59 bswap = 28,
60 asr = 29,
61 lsl = 30,
62 lsr = 31,
63};
64
65pub const Instruction = packed struct {
66 condition: ExecutionCondition,
67 input0: InputBehaviour,
68 input1: InputBehaviour,
69 modify_flags: bool,
70 output: OutputBehaviour,
71 command: Command,
72 reserved: u1 = 0,
73
74 pub fn format(instr: Instruction, comptime fmt: []const u8, options: std.fmt.FormatOptions, out: anytype) !void {
75 try std.fmt.format(out, "0x{x:0<4} ", .{@bitCast(u16, instr)});
76 try out.writeAll(switch (instr.condition) {
77 .always => " ",
78 .when_zero => "== 0",
79 .not_zero => "!= 0",
80 .greater_zero => " > 0",
81 .less_than_zero => " < 0",
82 .greater_or_equal_zero => ">= 0",
83 .less_or_equal_zero => "<= 0",
84 .overflow => "ovfl",
85 });
86 try out.writeAll(" ");
87 try out.writeAll(switch (instr.input0) {
88 .zero => "zero",
89 .immediate => "imm ",
90 .peek => "peek",
91 .pop => "pop ",
92 });
93 try out.writeAll(" ");
94 try out.writeAll(switch (instr.input1) {
95 .zero => "zero",
96 .immediate => "imm ",
97 .peek => "peek",
98 .pop => "pop ",
99 });
100 try out.writeAll(" ");
101 try out.writeAll(switch (instr.command) {
102 .copy => "copy ",
103 .ipget => "ipget ",
104 .get => "get ",
105 .set => "set ",
106 .store8 => "store8 ",
107 .store16 => "store16 ",
108 .load8 => "load8 ",
109 .load16 => "load16 ",
110 .undefined0 => "undefined",
111 .undefined1 => "undefined",
112 .frget => "frget ",
113 .frset => "frset ",
114 .bpget => "bpget ",
115 .bpset => "bpset ",
116 .spget => "spget ",
117 .spset => "spset ",
118 .add => "add ",
119 .sub => "sub ",
120 .mul => "mul ",
121 .div => "div ",
122 .mod => "mod ",
123 .@"and" => "and ",
124 .@"or" => "or ",
125 .xor => "xor ",
126 .not => "not ",
127 .signext => "signext ",
128 .rol => "rol ",
129 .ror => "ror ",
130 .bswap => "bswap ",
131 .asr => "asr ",
132 .lsl => "lsl ",
133 .lsr => "lsr ",
134 });
135 try out.writeAll(" ");
136 try out.writeAll(switch (instr.output) {
137 .discard => "discard",
138 .push => "push ",
139 .jump => "jmp ",
140 .jump_relative => "rjmp ",
141 });
142 try out.writeAll(" ");
143 try out.writeAll(if (instr.modify_flags)
144 "+ flags"
145 else
146 " ");
147 }
148};
149
150pub const FlagRegister = packed struct {
151 zero: bool,
152 negative: bool,
153 carry: bool,
154 carry_enabled: bool,
155 interrupt0_enabled: bool,
156 interrupt1_enabled: bool,
157 interrupt2_enabled: bool,
158 interrupt3_enabled: bool,
159 reserved: u8 = 0,
160};
161
162pub const Register = enum {
163 dummy,
164
165 pub fn allocIndex(self: Register) ?u4 {
166 return null;
167 }
168};
169
170pub const callee_preserved_regs = [_]Register{};
src/codegen/spu-mk2/interpreter.zig deleted-166
...@@ -1,166 +0,0 @@
1const std = @import("std");
2const log = std.log.scoped(.SPU_2_Interpreter);
3const spu = @import("../spu-mk2.zig");
4const FlagRegister = spu.FlagRegister;
5const Instruction = spu.Instruction;
6const ExecutionCondition = spu.ExecutionCondition;
7
8pub fn Interpreter(comptime Bus: type) type {
9 return struct {
10 ip: u16 = 0,
11 sp: u16 = undefined,
12 bp: u16 = undefined,
13 fr: FlagRegister = @bitCast(FlagRegister, @as(u16, 0)),
14 /// This is set to true when we hit an undefined0 instruction, allowing it to
15 /// be used as a trap for testing purposes
16 undefined0: bool = false,
17 /// This is set to true when we hit an undefined1 instruction, allowing it to
18 /// be used as a trap for testing purposes. undefined1 is used as a breakpoint.
19 undefined1: bool = false,
20 bus: Bus,
21
22 pub fn ExecuteBlock(self: *@This(), comptime size: ?u32) !void {
23 var count: usize = 0;
24 while (size == null or count < size.?) {
25 count += 1;
26 var instruction = @bitCast(Instruction, self.bus.read16(self.ip));
27
28 log.debug("Executing {}\n", .{instruction});
29
30 self.ip +%= 2;
31
32 const execute = switch (instruction.condition) {
33 .always => true,
34 .not_zero => !self.fr.zero,
35 .when_zero => self.fr.zero,
36 .overflow => self.fr.carry,
37 ExecutionCondition.greater_or_equal_zero => !self.fr.negative,
38 else => return error.Unimplemented,
39 };
40
41 if (execute) {
42 const val0 = switch (instruction.input0) {
43 .zero => @as(u16, 0),
44 .immediate => i: {
45 const val = self.bus.read16(@intCast(u16, self.ip));
46 self.ip +%= 2;
47 break :i val;
48 },
49 else => |e| e: {
50 // peek or pop; show value at current SP, and if pop, increment sp
51 const val = self.bus.read16(self.sp);
52 if (e == .pop) {
53 self.sp +%= 2;
54 }
55 break :e val;
56 },
57 };
58 const val1 = switch (instruction.input1) {
59 .zero => @as(u16, 0),
60 .immediate => i: {
61 const val = self.bus.read16(@intCast(u16, self.ip));
62 self.ip +%= 2;
63 break :i val;
64 },
65 else => |e| e: {
66 // peek or pop; show value at current SP, and if pop, increment sp
67 const val = self.bus.read16(self.sp);
68 if (e == .pop) {
69 self.sp +%= 2;
70 }
71 break :e val;
72 },
73 };
74
75 const output: u16 = switch (instruction.command) {
76 .get => self.bus.read16(self.bp +% (2 *% val0)),
77 .set => a: {
78 self.bus.write16(self.bp +% 2 *% val0, val1);
79 break :a val1;
80 },
81 .load8 => self.bus.read8(val0),
82 .load16 => self.bus.read16(val0),
83 .store8 => a: {
84 const val = @truncate(u8, val1);
85 self.bus.write8(val0, val);
86 break :a val;
87 },
88 .store16 => a: {
89 self.bus.write16(val0, val1);
90 break :a val1;
91 },
92 .copy => val0,
93 .add => a: {
94 var val: u16 = undefined;
95 self.fr.carry = @addWithOverflow(u16, val0, val1, &val);
96 break :a val;
97 },
98 .sub => a: {
99 var val: u16 = undefined;
100 self.fr.carry = @subWithOverflow(u16, val0, val1, &val);
101 break :a val;
102 },
103 .spset => a: {
104 self.sp = val0;
105 break :a val0;
106 },
107 .bpset => a: {
108 self.bp = val0;
109 break :a val0;
110 },
111 .frset => a: {
112 const val = (@bitCast(u16, self.fr) & val1) | (val0 & ~val1);
113 self.fr = @bitCast(FlagRegister, val);
114 break :a val;
115 },
116 .bswap => (val0 >> 8) | (val0 << 8),
117 .bpget => self.bp,
118 .spget => self.sp,
119 .ipget => self.ip +% (2 *% val0),
120 .lsl => val0 << 1,
121 .lsr => val0 >> 1,
122 .@"and" => val0 & val1,
123 .@"or" => val0 | val1,
124 .xor => val0 ^ val1,
125 .not => ~val0,
126 .undefined0 => {
127 self.undefined0 = true;
128 // Break out of the loop, and let the caller decide what to do
129 return;
130 },
131 .undefined1 => {
132 self.undefined1 = true;
133 // Break out of the loop, and let the caller decide what to do
134 return;
135 },
136 .signext => if ((val0 & 0x80) != 0)
137 (val0 & 0xFF) | 0xFF00
138 else
139 (val0 & 0xFF),
140 else => return error.Unimplemented,
141 };
142
143 switch (instruction.output) {
144 .discard => {},
145 .push => {
146 self.sp -%= 2;
147 self.bus.write16(self.sp, output);
148 },
149 .jump => {
150 self.ip = output;
151 },
152 else => return error.Unimplemented,
153 }
154 if (instruction.modify_flags) {
155 self.fr.negative = (output & 0x8000) != 0;
156 self.fr.zero = (output == 0x0000);
157 }
158 } else {
159 if (instruction.input0 == .immediate) self.ip +%= 2;
160 if (instruction.input1 == .immediate) self.ip +%= 2;
161 break;
162 }
163 }
164 }
165 };
166}
src/codegen/wasm.zig+2-1
...@@ -591,7 +591,8 @@ pub const Context = struct {...@@ -591,7 +591,8 @@ pub const Context = struct {
591 }591 }
592592
593 fn genFunctype(self: *Context) InnerError!void {593 fn genFunctype(self: *Context) InnerError!void {
594 const ty = self.decl.typed_value.most_recent.typed_value.ty;594 assert(self.decl.has_tv);
595 const ty = self.decl.ty;
595 const writer = self.func_type_data.writer();596 const writer = self.func_type_data.writer();
596597
597 try writer.writeByte(wasm.function_type);598 try writer.writeByte(wasm.function_type);
src/codegen/x86_64.zig+1-1
...@@ -171,7 +171,7 @@ pub const Encoder = struct {...@@ -171,7 +171,7 @@ pub const Encoder = struct {
171 /// This is because the helper functions will assume capacity171 /// This is because the helper functions will assume capacity
172 /// in order to avoid bounds checking.172 /// in order to avoid bounds checking.
173 pub fn init(code: *ArrayList(u8), maximum_inst_size: u8) !Self {173 pub fn init(code: *ArrayList(u8), maximum_inst_size: u8) !Self {
174 try code.ensureCapacity(code.items.len + maximum_inst_size);174 try code.ensureUnusedCapacity(maximum_inst_size);
175 return Self{ .code = code };175 return Self{ .code = code };
176 }176 }
177177
src/ir.zig+6-3
...@@ -255,6 +255,9 @@ pub const Inst = struct {...@@ -255,6 +255,9 @@ pub const Inst = struct {
255 }255 }
256256
257 /// Returns `null` if runtime-known.257 /// Returns `null` if runtime-known.
258 /// Should be called by codegen, not by Sema. Sema functions should call
259 /// `resolvePossiblyUndefinedValue` or `resolveDefinedValue` instead.
260 /// TODO audit Sema code for violations to the above guidance.
258 pub fn value(base: *Inst) ?Value {261 pub fn value(base: *Inst) ?Value {
259 if (base.ty.onePossibleValue()) |opv| return opv;262 if (base.ty.onePossibleValue()) |opv| return opv;
260263
...@@ -372,8 +375,7 @@ pub const Inst = struct {...@@ -372,8 +375,7 @@ pub const Inst = struct {
372 base: Inst,375 base: Inst,
373 asm_source: []const u8,376 asm_source: []const u8,
374 is_volatile: bool,377 is_volatile: bool,
375 output: ?*Inst,378 output_constraint: ?[]const u8,
376 output_name: ?[]const u8,
377 inputs: []const []const u8,379 inputs: []const []const u8,
378 clobbers: []const []const u8,380 clobbers: []const []const u8,
379 args: []const *Inst,381 args: []const *Inst,
...@@ -623,7 +625,8 @@ pub const Inst = struct {...@@ -623,7 +625,8 @@ pub const Inst = struct {
623 pub const base_tag = Tag.dbg_stmt;625 pub const base_tag = Tag.dbg_stmt;
624626
625 base: Inst,627 base: Inst,
626 byte_offset: u32,628 line: u32,
629 column: u32,
627630
628 pub fn operandCount(self: *const DbgStmt) usize {631 pub fn operandCount(self: *const DbgStmt) usize {
629 return 0;632 return 0;
src/libc_installation.zig+2-2
...@@ -383,7 +383,7 @@ pub const LibCInstallation = struct {...@@ -383,7 +383,7 @@ pub const LibCInstallation = struct {
383 var result_buf = std.ArrayList(u8).init(allocator);383 var result_buf = std.ArrayList(u8).init(allocator);
384 defer result_buf.deinit();384 defer result_buf.deinit();
385385
386 const arch_sub_dir = switch (builtin.arch) {386 const arch_sub_dir = switch (builtin.target.cpu.arch) {
387 .i386 => "x86",387 .i386 => "x86",
388 .x86_64 => "x64",388 .x86_64 => "x64",
389 .arm, .armeb => "arm",389 .arm, .armeb => "arm",
...@@ -437,7 +437,7 @@ pub const LibCInstallation = struct {...@@ -437,7 +437,7 @@ pub const LibCInstallation = struct {
437 var result_buf = std.ArrayList(u8).init(allocator);437 var result_buf = std.ArrayList(u8).init(allocator);
438 defer result_buf.deinit();438 defer result_buf.deinit();
439439
440 const arch_sub_dir = switch (builtin.arch) {440 const arch_sub_dir = switch (builtin.target.cpu.arch) {
441 .i386 => "x86",441 .i386 => "x86",
442 .x86_64 => "x64",442 .x86_64 => "x64",
443 .arm, .armeb => "arm",443 .arm, .armeb => "arm",
src/link.zig+12-1
...@@ -30,7 +30,7 @@ pub const Options = struct {...@@ -30,7 +30,7 @@ pub const Options = struct {
30 target: std.Target,30 target: std.Target,
31 output_mode: std.builtin.OutputMode,31 output_mode: std.builtin.OutputMode,
32 link_mode: std.builtin.LinkMode,32 link_mode: std.builtin.LinkMode,
33 object_format: std.builtin.ObjectFormat,33 object_format: std.Target.ObjectFormat,
34 optimize_mode: std.builtin.Mode,34 optimize_mode: std.builtin.Mode,
35 machine_code_model: std.builtin.CodeModel,35 machine_code_model: std.builtin.CodeModel,
36 root_name: []const u8,36 root_name: []const u8,
...@@ -301,6 +301,8 @@ pub const File = struct {...@@ -301,6 +301,8 @@ pub const File = struct {
301 /// May be called before or after updateDeclExports but must be called301 /// May be called before or after updateDeclExports but must be called
302 /// after allocateDeclIndexes for any given Decl.302 /// after allocateDeclIndexes for any given Decl.
303 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {303 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
304 log.debug("updateDecl {*} ({s}), type={}", .{ decl, decl.name, decl.ty });
305 assert(decl.has_tv);
304 switch (base.tag) {306 switch (base.tag) {
305 .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl),307 .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl),
306 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),308 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
...@@ -312,6 +314,10 @@ pub const File = struct {...@@ -312,6 +314,10 @@ pub const File = struct {
312 }314 }
313315
314 pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void {316 pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void {
317 log.debug("updateDeclLineNumber {*} ({s}), line={}", .{
318 decl, decl.name, decl.src_line + 1,
319 });
320 assert(decl.has_tv);
315 switch (base.tag) {321 switch (base.tag) {
316 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclLineNumber(module, decl),322 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclLineNumber(module, decl),
317 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),323 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),
...@@ -324,6 +330,7 @@ pub const File = struct {...@@ -324,6 +330,7 @@ pub const File = struct {
324 /// Must be called before any call to updateDecl or updateDeclExports for330 /// Must be called before any call to updateDecl or updateDeclExports for
325 /// any given Decl.331 /// any given Decl.
326 pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {332 pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {
333 log.debug("allocateDeclIndexes {*} ({s})", .{ decl, decl.name });
327 switch (base.tag) {334 switch (base.tag) {
328 .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl),335 .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl),
329 .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),336 .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),
...@@ -351,6 +358,7 @@ pub const File = struct {...@@ -351,6 +358,7 @@ pub const File = struct {
351 base.releaseLock();358 base.releaseLock();
352 if (base.file) |f| f.close();359 if (base.file) |f| f.close();
353 if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path);360 if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path);
361 base.options.system_libs.deinit(base.allocator);
354 switch (base.tag) {362 switch (base.tag) {
355 .coff => {363 .coff => {
356 const parent = @fieldParentPtr(Coff, "base", base);364 const parent = @fieldParentPtr(Coff, "base", base);
...@@ -434,6 +442,7 @@ pub const File = struct {...@@ -434,6 +442,7 @@ pub const File = struct {
434442
435 /// Called when a Decl is deleted from the Module.443 /// Called when a Decl is deleted from the Module.
436 pub fn freeDecl(base: *File, decl: *Module.Decl) void {444 pub fn freeDecl(base: *File, decl: *Module.Decl) void {
445 log.debug("freeDecl {*} ({s})", .{ decl, decl.name });
437 switch (base.tag) {446 switch (base.tag) {
438 .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl),447 .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl),
439 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl),448 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl),
...@@ -462,6 +471,8 @@ pub const File = struct {...@@ -462,6 +471,8 @@ pub const File = struct {
462 decl: *Module.Decl,471 decl: *Module.Decl,
463 exports: []const *Module.Export,472 exports: []const *Module.Export,
464 ) !void {473 ) !void {
474 log.debug("updateDeclExports {*} ({s})", .{ decl, decl.name });
475 assert(decl.has_tv);
465 switch (base.tag) {476 switch (base.tag) {
466 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclExports(module, decl, exports),477 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclExports(module, decl, exports),
467 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports),478 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports),
src/link/C.zig+54-53
...@@ -15,6 +15,10 @@ pub const base_tag: link.File.Tag = .c;...@@ -15,6 +15,10 @@ pub const base_tag: link.File.Tag = .c;
15pub const zig_h = @embedFile("C/zig.h");15pub const zig_h = @embedFile("C/zig.h");
1616
17base: link.File,17base: link.File,
18/// This linker backend does not try to incrementally link output C source code.
19/// Instead, it tracks all declarations in this table, and iterates over it
20/// in the flush function, stitching pre-rendered pieces of C code together.
21decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, void) = .{},
1822
19/// Per-declaration data. For functions this is the body, and23/// Per-declaration data. For functions this is the body, and
20/// the forward declaration is stored in the FnBlock.24/// the forward declaration is stored in the FnBlock.
...@@ -66,15 +70,16 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -66,15 +70,16 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
66}70}
6771
68pub fn deinit(self: *C) void {72pub fn deinit(self: *C) void {
69 const module = self.base.options.module orelse return;73 for (self.decl_table.items()) |entry| {
70 for (module.decl_table.items()) |entry| {74 self.freeDecl(entry.key);
71 self.freeDecl(entry.value);
72 }75 }
76 self.decl_table.deinit(self.base.allocator);
73}77}
7478
75pub fn allocateDeclIndexes(self: *C, decl: *Module.Decl) !void {}79pub fn allocateDeclIndexes(self: *C, decl: *Module.Decl) !void {}
7680
77pub fn freeDecl(self: *C, decl: *Module.Decl) void {81pub fn freeDecl(self: *C, decl: *Module.Decl) void {
82 _ = self.decl_table.swapRemove(decl);
78 decl.link.c.code.deinit(self.base.allocator);83 decl.link.c.code.deinit(self.base.allocator);
79 decl.fn_link.c.fwd_decl.deinit(self.base.allocator);84 decl.fn_link.c.fwd_decl.deinit(self.base.allocator);
80 var it = decl.fn_link.c.typedefs.iterator();85 var it = decl.fn_link.c.typedefs.iterator();
...@@ -88,6 +93,9 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {...@@ -88,6 +93,9 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
88 const tracy = trace(@src());93 const tracy = trace(@src());
89 defer tracy.end();94 defer tracy.end();
9095
96 // Keep track of all decls so we can iterate over them on flush().
97 _ = try self.decl_table.getOrPut(self.base.allocator, decl);
98
91 const fwd_decl = &decl.fn_link.c.fwd_decl;99 const fwd_decl = &decl.fn_link.c.fwd_decl;
92 const typedefs = &decl.fn_link.c.typedefs;100 const typedefs = &decl.fn_link.c.typedefs;
93 const code = &decl.link.c.code;101 const code = &decl.link.c.code;
...@@ -168,7 +176,7 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {...@@ -168,7 +176,7 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
168 defer all_buffers.deinit();176 defer all_buffers.deinit();
169177
170 // This is at least enough until we get to the function bodies without error handling.178 // This is at least enough until we get to the function bodies without error handling.
171 try all_buffers.ensureCapacity(module.decl_table.count() + 2);179 try all_buffers.ensureCapacity(self.decl_table.count() + 2);
172180
173 var file_size: u64 = zig_h.len;181 var file_size: u64 = zig_h.len;
174 all_buffers.appendAssumeCapacity(.{182 all_buffers.appendAssumeCapacity(.{
...@@ -197,36 +205,32 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {...@@ -197,36 +205,32 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
197 // Typedefs, forward decls and non-functions first.205 // Typedefs, forward decls and non-functions first.
198 // TODO: performance investigation: would keeping a list of Decls that we should206 // TODO: performance investigation: would keeping a list of Decls that we should
199 // generate, rather than querying here, be faster?207 // generate, rather than querying here, be faster?
200 for (module.decl_table.items()) |kv| {208 for (self.decl_table.items()) |kv| {
201 const decl = kv.value;209 const decl = kv.key;
202 switch (decl.typed_value) {210 if (!decl.has_tv) continue;
203 .most_recent => |tvm| {211 const buf = buf: {
204 const buf = buf: {212 if (decl.val.castTag(.function)) |_| {
205 if (tvm.typed_value.val.castTag(.function)) |_| {213 var it = decl.fn_link.c.typedefs.iterator();
206 var it = decl.fn_link.c.typedefs.iterator();214 while (it.next()) |new| {
207 while (it.next()) |new| {215 if (typedefs.get(new.key)) |previous| {
208 if (typedefs.get(new.key)) |previous| {216 try err_typedef_writer.print("typedef {s} {s};\n", .{ previous, new.value.name });
209 try err_typedef_writer.print("typedef {s} {s};\n", .{ previous, new.value.name });
210 } else {
211 try typedefs.ensureCapacity(typedefs.capacity() + 1);
212 try err_typedef_writer.writeAll(new.value.rendered);
213 typedefs.putAssumeCapacityNoClobber(new.key, new.value.name);
214 }
215 }
216 fn_count += 1;
217 break :buf decl.fn_link.c.fwd_decl.items;
218 } else {217 } else {
219 break :buf decl.link.c.code.items;218 try typedefs.ensureCapacity(typedefs.capacity() + 1);
219 try err_typedef_writer.writeAll(new.value.rendered);
220 typedefs.putAssumeCapacityNoClobber(new.key, new.value.name);
220 }221 }
221 };222 }
222 all_buffers.appendAssumeCapacity(.{223 fn_count += 1;
223 .iov_base = buf.ptr,224 break :buf decl.fn_link.c.fwd_decl.items;
224 .iov_len = buf.len,225 } else {
225 });226 break :buf decl.link.c.code.items;
226 file_size += buf.len;227 }
227 },228 };
228 .never_succeeded => continue,229 all_buffers.appendAssumeCapacity(.{
229 }230 .iov_base = buf.ptr,
231 .iov_len = buf.len,
232 });
233 file_size += buf.len;
230 }234 }
231235
232 err_typedef_item.* = .{236 err_typedef_item.* = .{
...@@ -237,20 +241,16 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {...@@ -237,20 +241,16 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
237241
238 // Now the function bodies.242 // Now the function bodies.
239 try all_buffers.ensureCapacity(all_buffers.items.len + fn_count);243 try all_buffers.ensureCapacity(all_buffers.items.len + fn_count);
240 for (module.decl_table.items()) |kv| {244 for (self.decl_table.items()) |kv| {
241 const decl = kv.value;245 const decl = kv.key;
242 switch (decl.typed_value) {246 if (!decl.has_tv) continue;
243 .most_recent => |tvm| {247 if (decl.val.castTag(.function)) |_| {
244 if (tvm.typed_value.val.castTag(.function)) |_| {248 const buf = decl.link.c.code.items;
245 const buf = decl.link.c.code.items;249 all_buffers.appendAssumeCapacity(.{
246 all_buffers.appendAssumeCapacity(.{250 .iov_base = buf.ptr,
247 .iov_base = buf.ptr,251 .iov_len = buf.len,
248 .iov_len = buf.len,252 });
249 });253 file_size += buf.len;
250 file_size += buf.len;
251 }
252 },
253 .never_succeeded => continue,
254 }254 }
255 }255 }
256256
...@@ -263,13 +263,13 @@ pub fn flushEmitH(module: *Module) !void {...@@ -263,13 +263,13 @@ pub fn flushEmitH(module: *Module) !void {
263 const tracy = trace(@src());263 const tracy = trace(@src());
264 defer tracy.end();264 defer tracy.end();
265265
266 const emit_h_loc = module.emit_h orelse return;266 const emit_h = module.emit_h orelse return;
267267
268 // We collect a list of buffers to write, and write them all at once with pwritev 😎268 // We collect a list of buffers to write, and write them all at once with pwritev 😎
269 var all_buffers = std.ArrayList(std.os.iovec_const).init(module.gpa);269 var all_buffers = std.ArrayList(std.os.iovec_const).init(module.gpa);
270 defer all_buffers.deinit();270 defer all_buffers.deinit();
271271
272 try all_buffers.ensureCapacity(module.decl_table.count() + 1);272 try all_buffers.ensureCapacity(emit_h.decl_table.count() + 1);
273273
274 var file_size: u64 = zig_h.len;274 var file_size: u64 = zig_h.len;
275 all_buffers.appendAssumeCapacity(.{275 all_buffers.appendAssumeCapacity(.{
...@@ -277,9 +277,10 @@ pub fn flushEmitH(module: *Module) !void {...@@ -277,9 +277,10 @@ pub fn flushEmitH(module: *Module) !void {
277 .iov_len = zig_h.len,277 .iov_len = zig_h.len,
278 });278 });
279279
280 for (module.decl_table.items()) |kv| {280 for (emit_h.decl_table.items()) |kv| {
281 const emit_h = kv.value.getEmitH(module);281 const decl = kv.key;
282 const buf = emit_h.fwd_decl.items;282 const decl_emit_h = decl.getEmitH(module);
283 const buf = decl_emit_h.fwd_decl.items;
283 all_buffers.appendAssumeCapacity(.{284 all_buffers.appendAssumeCapacity(.{
284 .iov_base = buf.ptr,285 .iov_base = buf.ptr,
285 .iov_len = buf.len,286 .iov_len = buf.len,
...@@ -287,8 +288,8 @@ pub fn flushEmitH(module: *Module) !void {...@@ -287,8 +288,8 @@ pub fn flushEmitH(module: *Module) !void {
287 file_size += buf.len;288 file_size += buf.len;
288 }289 }
289290
290 const directory = emit_h_loc.directory orelse module.comp.local_cache_directory;291 const directory = emit_h.loc.directory orelse module.comp.local_cache_directory;
291 const file = try directory.handle.createFile(emit_h_loc.basename, .{292 const file = try directory.handle.createFile(emit_h.loc.basename, .{
292 // We set the end position explicitly below; by not truncating the file, we possibly293 // We set the end position explicitly below; by not truncating the file, we possibly
293 // make it easier on the file system by doing 1 reallocation instead of two.294 // make it easier on the file system by doing 1 reallocation instead of two.
294 .truncate = false,295 .truncate = false,
src/link/C/zig.h+18-14
...@@ -1,25 +1,15 @@...@@ -1,25 +1,15 @@
1#if __STDC_VERSION__ >= 199901L
2#include <stdbool.h>
3#else
4#define bool unsigned char
5#define true 1
6#define false 0
7#endif
8
9#if __STDC_VERSION__ >= 201112L1#if __STDC_VERSION__ >= 201112L
10#define zig_noreturn _Noreturn2#define zig_noreturn _Noreturn
3#define zig_threadlocal thread_local
11#elif __GNUC__4#elif __GNUC__
12#define zig_noreturn __attribute__ ((noreturn))5#define zig_noreturn __attribute__ ((noreturn))
6#define zig_threadlocal __thread
13#elif _MSC_VER7#elif _MSC_VER
14#define zig_noreturn __declspec(noreturn)8#define zig_noreturn __declspec(noreturn)
9#define zig_threadlocal __declspec(thread)
15#else10#else
16#define zig_noreturn11#define zig_noreturn
17#endif12#define zig_threadlocal zig_threadlocal_unavailable
18
19#if defined(__GNUC__)
20#define zig_unreachable() __builtin_unreachable()
21#else
22#define zig_unreachable()
23#endif13#endif
2414
25#if __STDC_VERSION__ >= 199901L15#if __STDC_VERSION__ >= 199901L
...@@ -30,6 +20,20 @@...@@ -30,6 +20,20 @@
30#define ZIG_RESTRICT20#define ZIG_RESTRICT
31#endif21#endif
3222
23#if __STDC_VERSION__ >= 199901L
24#include <stdbool.h>
25#else
26#define bool unsigned char
27#define true 1
28#define false 0
29#endif
30
31#if defined(__GNUC__)
32#define zig_unreachable() __builtin_unreachable()
33#else
34#define zig_unreachable()
35#endif
36
33#ifdef __cplusplus37#ifdef __cplusplus
34#define ZIG_EXTERN_C extern "C"38#define ZIG_EXTERN_C extern "C"
35#else39#else
src/link/Coff.zig+6-4
...@@ -662,15 +662,17 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {...@@ -662,15 +662,17 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
662 if (build_options.have_llvm)662 if (build_options.have_llvm)
663 if (self.llvm_object) |llvm_object| return try llvm_object.updateDecl(module, decl);663 if (self.llvm_object) |llvm_object| return try llvm_object.updateDecl(module, decl);
664664
665 const typed_value = decl.typed_value.most_recent.typed_value;665 if (decl.val.tag() == .extern_fn) {
666 if (typed_value.val.tag() == .extern_fn) {
667 return; // TODO Should we do more when front-end analyzed extern decl?666 return; // TODO Should we do more when front-end analyzed extern decl?
668 }667 }
669668
670 var code_buffer = std.ArrayList(u8).init(self.base.allocator);669 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
671 defer code_buffer.deinit();670 defer code_buffer.deinit();
672671
673 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none);672 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
673 .ty = decl.ty,
674 .val = decl.val,
675 }, &code_buffer, .none);
674 const code = switch (res) {676 const code = switch (res) {
675 .externally_managed => |x| x,677 .externally_managed => |x| x,
676 .appended => code_buffer.items,678 .appended => code_buffer.items,
...@@ -681,7 +683,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {...@@ -681,7 +683,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
681 },683 },
682 };684 };
683685
684 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);686 const required_alignment = decl.ty.abiAlignment(self.base.options.target);
685 const curr_size = decl.link.coff.size;687 const curr_size = decl.link.coff.size;
686 if (curr_size != 0) {688 if (curr_size != 0) {
687 const capacity = decl.link.coff.capacity();689 const capacity = decl.link.coff.capacity();
src/link/Elf.zig+19-35
...@@ -2183,10 +2183,15 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2183,10 +2183,15 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2183 if (build_options.have_llvm)2183 if (build_options.have_llvm)
2184 if (self.llvm_object) |llvm_object| return try llvm_object.updateDecl(module, decl);2184 if (self.llvm_object) |llvm_object| return try llvm_object.updateDecl(module, decl);
21852185
2186 const typed_value = decl.typed_value.most_recent.typed_value;2186 if (decl.val.tag() == .extern_fn) {
2187 if (typed_value.val.tag() == .extern_fn) {
2188 return; // TODO Should we do more when front-end analyzed extern decl?2187 return; // TODO Should we do more when front-end analyzed extern decl?
2189 }2188 }
2189 if (decl.val.castTag(.variable)) |payload| {
2190 const variable = payload.data;
2191 if (variable.is_extern) {
2192 return; // TODO Should we do more when front-end analyzed extern decl?
2193 }
2194 }
21902195
2191 var code_buffer = std.ArrayList(u8).init(self.base.allocator);2196 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
2192 defer code_buffer.deinit();2197 defer code_buffer.deinit();
...@@ -2206,7 +2211,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2206,7 +2211,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2206 dbg_info_type_relocs.deinit(self.base.allocator);2211 dbg_info_type_relocs.deinit(self.base.allocator);
2207 }2212 }
22082213
2209 const is_fn: bool = switch (typed_value.ty.zigTypeTag()) {2214 const is_fn: bool = switch (decl.ty.zigTypeTag()) {
2210 .Fn => true,2215 .Fn => true,
2211 else => false,2216 else => false,
2212 };2217 };
...@@ -2214,21 +2219,8 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2214,21 +2219,8 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2214 // For functions we need to add a prologue to the debug line program.2219 // For functions we need to add a prologue to the debug line program.
2215 try dbg_line_buffer.ensureCapacity(26);2220 try dbg_line_buffer.ensureCapacity(26);
22162221
2217 const line_off: u28 = blk: {2222 const func = decl.val.castTag(.function).?.data;
2218 const tree = decl.container.file_scope.tree;2223 const line_off = @intCast(u28, decl.src_line + func.lbrace_line);
2219 const node_tags = tree.nodes.items(.tag);
2220 const node_datas = tree.nodes.items(.data);
2221 const token_starts = tree.tokens.items(.start);
2222
2223 // TODO Look into improving the performance here by adding a token-index-to-line
2224 // lookup table. Currently this involves scanning over the source code for newlines.
2225 const fn_decl = decl.src_node;
2226 assert(node_tags[fn_decl] == .fn_decl);
2227 const block = node_datas[fn_decl].rhs;
2228 const lbrace = tree.firstToken(block);
2229 const line_delta = std.zig.lineDelta(tree.source, 0, token_starts[lbrace]);
2230 break :blk @intCast(u28, line_delta);
2231 };
22322224
2233 const ptr_width_bytes = self.ptrWidthBytes();2225 const ptr_width_bytes = self.ptrWidthBytes();
2234 dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{2226 dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{
...@@ -2262,7 +2254,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2262,7 +2254,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2262 const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1];2254 const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1];
2263 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 25 + decl_name_with_null.len);2255 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 25 + decl_name_with_null.len);
22642256
2265 const fn_ret_type = typed_value.ty.fnReturnType();2257 const fn_ret_type = decl.ty.fnReturnType();
2266 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();2258 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();
2267 if (fn_ret_has_bits) {2259 if (fn_ret_has_bits) {
2268 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);2260 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);
...@@ -2291,7 +2283,11 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2291,7 +2283,11 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2291 } else {2283 } else {
2292 // TODO implement .debug_info for global variables2284 // TODO implement .debug_info for global variables
2293 }2285 }
2294 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{2286 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
2287 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2288 .ty = decl.ty,
2289 .val = decl_val,
2290 }, &code_buffer, .{
2295 .dwarf = .{2291 .dwarf = .{
2296 .dbg_line = &dbg_line_buffer,2292 .dbg_line = &dbg_line_buffer,
2297 .dbg_info = &dbg_info_buffer,2293 .dbg_info = &dbg_info_buffer,
...@@ -2308,7 +2304,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2308,7 +2304,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2308 },2304 },
2309 };2305 };
23102306
2311 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);2307 const required_alignment = decl.ty.abiAlignment(self.base.options.target);
23122308
2313 const stt_bits: u8 = if (is_fn) elf.STT_FUNC else elf.STT_OBJECT;2309 const stt_bits: u8 = if (is_fn) elf.STT_FUNC else elf.STT_OBJECT;
23142310
...@@ -2670,7 +2666,6 @@ pub fn updateDeclExports(...@@ -2670,7 +2666,6 @@ pub fn updateDeclExports(
2670 defer tracy.end();2666 defer tracy.end();
26712667
2672 try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len);2668 try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len);
2673 const typed_value = decl.typed_value.most_recent.typed_value;
2674 if (decl.link.elf.local_sym_index == 0) return;2669 if (decl.link.elf.local_sym_index == 0) return;
2675 const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index];2670 const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index];
26762671
...@@ -2741,19 +2736,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec...@@ -2741,19 +2736,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
27412736
2742 if (self.llvm_object) |_| return;2737 if (self.llvm_object) |_| return;
27432738
2744 const tree = decl.container.file_scope.tree;2739 const func = decl.val.castTag(.function).?.data;
2745 const node_tags = tree.nodes.items(.tag);2740 const casted_line_off = @intCast(u28, decl.src_line + func.lbrace_line);
2746 const node_datas = tree.nodes.items(.data);
2747 const token_starts = tree.tokens.items(.start);
2748
2749 // TODO Look into improving the performance here by adding a token-index-to-line
2750 // lookup table. Currently this involves scanning over the source code for newlines.
2751 const fn_decl = decl.src_node;
2752 assert(node_tags[fn_decl] == .fn_decl);
2753 const block = node_datas[fn_decl].rhs;
2754 const lbrace = tree.firstToken(block);
2755 const line_delta = std.zig.lineDelta(tree.source, 0, token_starts[lbrace]);
2756 const casted_line_off = @intCast(u28, line_delta);
27572741
2758 const shdr = &self.sections.items[self.debug_line_section_index.?];2742 const shdr = &self.sections.items[self.debug_line_section_index.?];
2759 const file_pos = shdr.sh_offset + decl.fn_link.elf.off + self.getRelocDbgLineOff();2743 const file_pos = shdr.sh_offset + decl.fn_link.elf.off + self.getRelocDbgLineOff();
src/link/MachO.zig+56-5
...@@ -1200,6 +1200,15 @@ fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {...@@ -1200,6 +1200,15 @@ fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {
1200 // TODO shrink the __text section size here1200 // TODO shrink the __text section size here
1201 self.last_text_block = text_block.prev;1201 self.last_text_block = text_block.prev;
1202 }1202 }
1203 if (self.d_sym) |*ds| {
1204 if (ds.dbg_info_decl_first == text_block) {
1205 ds.dbg_info_decl_first = text_block.dbg_info_next;
1206 }
1207 if (ds.dbg_info_decl_last == text_block) {
1208 // TODO shrink the .debug_info section size here
1209 ds.dbg_info_decl_last = text_block.dbg_info_prev;
1210 }
1211 }
12031212
1204 if (text_block.prev) |prev| {1213 if (text_block.prev) |prev| {
1205 prev.next = text_block.next;1214 prev.next = text_block.next;
...@@ -1218,6 +1227,20 @@ fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {...@@ -1218,6 +1227,20 @@ fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {
1218 } else {1227 } else {
1219 text_block.next = null;1228 text_block.next = null;
1220 }1229 }
1230
1231 if (text_block.dbg_info_prev) |prev| {
1232 prev.dbg_info_next = text_block.dbg_info_next;
1233
1234 // TODO the free list logic like we do for text blocks above
1235 } else {
1236 text_block.dbg_info_prev = null;
1237 }
1238
1239 if (text_block.dbg_info_next) |next| {
1240 next.dbg_info_prev = text_block.dbg_info_prev;
1241 } else {
1242 text_block.dbg_info_next = null;
1243 }
1221}1244}
12221245
1223fn shrinkTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64) void {1246fn shrinkTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64) void {
...@@ -1277,8 +1300,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1277,8 +1300,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1277 const tracy = trace(@src());1300 const tracy = trace(@src());
1278 defer tracy.end();1301 defer tracy.end();
12791302
1280 const typed_value = decl.typed_value.most_recent.typed_value;1303 if (decl.val.tag() == .extern_fn) {
1281 if (typed_value.val.tag() == .extern_fn) {
1282 return; // TODO Should we do more when front-end analyzed extern decl?1304 return; // TODO Should we do more when front-end analyzed extern decl?
1283 }1305 }
12841306
...@@ -1299,7 +1321,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1299,7 +1321,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1299 }1321 }
13001322
1301 const res = if (debug_buffers) |*dbg|1323 const res = if (debug_buffers) |*dbg|
1302 try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{1324 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
1325 .ty = decl.ty,
1326 .val = decl.val,
1327 }, &code_buffer, .{
1303 .dwarf = .{1328 .dwarf = .{
1304 .dbg_line = &dbg.dbg_line_buffer,1329 .dbg_line = &dbg.dbg_line_buffer,
1305 .dbg_info = &dbg.dbg_info_buffer,1330 .dbg_info = &dbg.dbg_info_buffer,
...@@ -1307,7 +1332,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1307,7 +1332,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1307 },1332 },
1308 })1333 })
1309 else1334 else
1310 try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none);1335 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
1336 .ty = decl.ty,
1337 .val = decl.val,
1338 }, &code_buffer, .none);
13111339
1312 const code = switch (res) {1340 const code = switch (res) {
1313 .externally_managed => |x| x,1341 .externally_managed => |x| x,
...@@ -1323,7 +1351,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1323,7 +1351,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1323 },1351 },
1324 };1352 };
13251353
1326 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);1354 const required_alignment = decl.ty.abiAlignment(self.base.options.target);
1327 assert(decl.link.macho.local_sym_index != 0); // Caller forgot to call allocateDeclIndexes()1355 assert(decl.link.macho.local_sym_index != 0); // Caller forgot to call allocateDeclIndexes()
1328 const symbol = &self.locals.items[decl.link.macho.local_sym_index];1356 const symbol = &self.locals.items[decl.link.macho.local_sym_index];
13291357
...@@ -1599,6 +1627,29 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {...@@ -1599,6 +1627,29 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {
15991627
1600 decl.link.macho.local_sym_index = 0;1628 decl.link.macho.local_sym_index = 0;
1601 }1629 }
1630 if (self.d_sym) |*ds| {
1631 // TODO make this logic match freeTextBlock. Maybe abstract the logic
1632 // out since the same thing is desired for both.
1633 _ = ds.dbg_line_fn_free_list.remove(&decl.fn_link.macho);
1634 if (decl.fn_link.macho.prev) |prev| {
1635 ds.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {};
1636 prev.next = decl.fn_link.macho.next;
1637 if (decl.fn_link.macho.next) |next| {
1638 next.prev = prev;
1639 } else {
1640 ds.dbg_line_fn_last = prev;
1641 }
1642 } else if (decl.fn_link.macho.next) |next| {
1643 ds.dbg_line_fn_first = next;
1644 next.prev = null;
1645 }
1646 if (ds.dbg_line_fn_first == &decl.fn_link.macho) {
1647 ds.dbg_line_fn_first = decl.fn_link.macho.next;
1648 }
1649 if (ds.dbg_line_fn_last == &decl.fn_link.macho) {
1650 ds.dbg_line_fn_last = decl.fn_link.macho.prev;
1651 }
1652 }
1602}1653}
16031654
1604pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 {1655pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 {
src/link/MachO/DebugSymbols.zig+16-46
...@@ -904,25 +904,19 @@ pub fn updateDeclLineNumber(self: *DebugSymbols, module: *Module, decl: *const M...@@ -904,25 +904,19 @@ pub fn updateDeclLineNumber(self: *DebugSymbols, module: *Module, decl: *const M
904 const tracy = trace(@src());904 const tracy = trace(@src());
905 defer tracy.end();905 defer tracy.end();
906906
907 const tree = decl.container.file_scope.tree;907 const tree = decl.namespace.file_scope.tree;
908 const node_tags = tree.nodes.items(.tag);908 const node_tags = tree.nodes.items(.tag);
909 const node_datas = tree.nodes.items(.data);909 const node_datas = tree.nodes.items(.data);
910 const token_starts = tree.tokens.items(.start);910 const token_starts = tree.tokens.items(.start);
911911
912 // TODO Look into improving the performance here by adding a token-index-to-line912 const func = decl.val.castTag(.function).?.data;
913 // lookup table. Currently this involves scanning over the source code for newlines.913 const line_off = @intCast(u28, decl.src_line + func.lbrace_line);
914 const fn_decl = decl.src_node;
915 assert(node_tags[fn_decl] == .fn_decl);
916 const block = node_datas[fn_decl].rhs;
917 const lbrace = tree.firstToken(block);
918 const line_delta = std.zig.lineDelta(tree.source, 0, token_starts[lbrace]);
919 const casted_line_off = @intCast(u28, line_delta);
920914
921 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;915 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
922 const shdr = &dwarf_segment.sections.items[self.debug_line_section_index.?];916 const shdr = &dwarf_segment.sections.items[self.debug_line_section_index.?];
923 const file_pos = shdr.offset + decl.fn_link.macho.off + getRelocDbgLineOff();917 const file_pos = shdr.offset + decl.fn_link.macho.off + getRelocDbgLineOff();
924 var data: [4]u8 = undefined;918 var data: [4]u8 = undefined;
925 leb.writeUnsignedFixed(4, &data, casted_line_off);919 leb.writeUnsignedFixed(4, &data, line_off);
926 try self.file.pwriteAll(&data, file_pos);920 try self.file.pwriteAll(&data, file_pos);
927}921}
928922
...@@ -946,27 +940,14 @@ pub fn initDeclDebugBuffers(...@@ -946,27 +940,14 @@ pub fn initDeclDebugBuffers(
946 var dbg_info_buffer = std.ArrayList(u8).init(allocator);940 var dbg_info_buffer = std.ArrayList(u8).init(allocator);
947 var dbg_info_type_relocs: link.File.DbgInfoTypeRelocsTable = .{};941 var dbg_info_type_relocs: link.File.DbgInfoTypeRelocsTable = .{};
948942
949 const typed_value = decl.typed_value.most_recent.typed_value;943 assert(decl.has_tv);
950 switch (typed_value.ty.zigTypeTag()) {944 switch (decl.ty.zigTypeTag()) {
951 .Fn => {945 .Fn => {
952 // For functions we need to add a prologue to the debug line program.946 // For functions we need to add a prologue to the debug line program.
953 try dbg_line_buffer.ensureCapacity(26);947 try dbg_line_buffer.ensureCapacity(26);
954948
955 const line_off: u28 = blk: {949 const func = decl.val.castTag(.function).?.data;
956 const tree = decl.container.file_scope.tree;950 const line_off = @intCast(u28, decl.src_line + func.lbrace_line);
957 const node_tags = tree.nodes.items(.tag);
958 const node_datas = tree.nodes.items(.data);
959 const token_starts = tree.tokens.items(.start);
960
961 // TODO Look into improving the performance here by adding a token-index-to-line
962 // lookup table. Currently this involves scanning over the source code for newlines.
963 const fn_decl = decl.src_node;
964 assert(node_tags[fn_decl] == .fn_decl);
965 const block = node_datas[fn_decl].rhs;
966 const lbrace = tree.firstToken(block);
967 const line_delta = std.zig.lineDelta(tree.source, 0, token_starts[lbrace]);
968 break :blk @intCast(u28, line_delta);
969 };
970951
971 dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{952 dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{
972 DW.LNS_extended_op,953 DW.LNS_extended_op,
...@@ -999,7 +980,7 @@ pub fn initDeclDebugBuffers(...@@ -999,7 +980,7 @@ pub fn initDeclDebugBuffers(
999 const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1];980 const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1];
1000 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 27 + decl_name_with_null.len);981 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 27 + decl_name_with_null.len);
1001982
1002 const fn_ret_type = typed_value.ty.fnReturnType();983 const fn_ret_type = decl.ty.fnReturnType();
1003 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();984 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();
1004 if (fn_ret_has_bits) {985 if (fn_ret_has_bits) {
1005 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);986 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);
...@@ -1058,8 +1039,8 @@ pub fn commitDeclDebugInfo(...@@ -1058,8 +1039,8 @@ pub fn commitDeclDebugInfo(
1058 const symbol = self.base.locals.items[decl.link.macho.local_sym_index];1039 const symbol = self.base.locals.items[decl.link.macho.local_sym_index];
1059 const text_block = &decl.link.macho;1040 const text_block = &decl.link.macho;
1060 // If the Decl is a function, we need to update the __debug_line program.1041 // If the Decl is a function, we need to update the __debug_line program.
1061 const typed_value = decl.typed_value.most_recent.typed_value;1042 assert(decl.has_tv);
1062 switch (typed_value.ty.zigTypeTag()) {1043 switch (decl.ty.zigTypeTag()) {
1063 .Fn => {1044 .Fn => {
1064 // Perform the relocations based on vaddr.1045 // Perform the relocations based on vaddr.
1065 {1046 {
...@@ -1082,22 +1063,8 @@ pub fn commitDeclDebugInfo(...@@ -1082,22 +1063,8 @@ pub fn commitDeclDebugInfo(
1082 try leb.writeULEB128(dbg_line_buffer.writer(), text_block.size);1063 try leb.writeULEB128(dbg_line_buffer.writer(), text_block.size);
10831064
1084 try dbg_line_buffer.append(DW.LNS_advance_line);1065 try dbg_line_buffer.append(DW.LNS_advance_line);
1085 const line_off: u28 = blk: {1066 const func = decl.val.castTag(.function).?.data;
1086 const tree = decl.container.file_scope.tree;1067 const line_off = @intCast(u28, func.rbrace_line - func.lbrace_line);
1087 const node_tags = tree.nodes.items(.tag);
1088 const node_datas = tree.nodes.items(.data);
1089 const token_starts = tree.tokens.items(.start);
1090
1091 // TODO Look into improving the performance here by adding a token-index-to-line
1092 // lookup table. Currently this involves scanning over the source code for newlines.
1093 const fn_decl = decl.src_node;
1094 assert(node_tags[fn_decl] == .fn_decl);
1095 const block = node_datas[fn_decl].rhs;
1096 const lbrace = tree.firstToken(block);
1097 const rbrace = tree.lastToken(block);
1098 const line_delta = std.zig.lineDelta(tree.source, token_starts[lbrace], token_starts[rbrace]);
1099 break :blk @intCast(u28, line_delta);
1100 };
1101 try leb.writeULEB128(dbg_line_buffer.writer(), line_off);1068 try leb.writeULEB128(dbg_line_buffer.writer(), line_off);
1102 }1069 }
11031070
...@@ -1188,6 +1155,9 @@ pub fn commitDeclDebugInfo(...@@ -1188,6 +1155,9 @@ pub fn commitDeclDebugInfo(
1188 else => {},1155 else => {},
1189 }1156 }
11901157
1158 if (dbg_info_buffer.items.len == 0)
1159 return;
1160
1191 // Now we emit the .debug_info types of the Decl. These will count towards the size of1161 // Now we emit the .debug_info types of the Decl. These will count towards the size of
1192 // the buffer, so we have to do it before computing the offset, and we can't perform the actual1162 // the buffer, so we have to do it before computing the offset, and we can't perform the actual
1193 // relocations yet.1163 // relocations yet.
src/link/SpirV.zig+25-16
...@@ -37,13 +37,17 @@ const spec = @import("../codegen/spirv/spec.zig");...@@ -37,13 +37,17 @@ const spec = @import("../codegen/spirv/spec.zig");
3737
38// TODO: Should this struct be used at all rather than just a hashmap of aux data for every decl?38// TODO: Should this struct be used at all rather than just a hashmap of aux data for every decl?
39pub const FnData = struct {39pub const FnData = struct {
40 // We're going to fill these in flushModule, and we're going to fill them unconditionally,40// We're going to fill these in flushModule, and we're going to fill them unconditionally,
41 // so just set it to undefined.41// so just set it to undefined.
42 id: u32 = undefined42id: u32 = undefined };
43};
4443
45base: link.File,44base: link.File,
4645
46/// This linker backend does not try to incrementally link output SPIR-V code.
47/// Instead, it tracks all declarations in this table, and iterates over it
48/// in the flush function.
49decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, void) = .{},
50
47pub fn createEmpty(gpa: *Allocator, options: link.Options) !*SpirV {51pub fn createEmpty(gpa: *Allocator, options: link.Options) !*SpirV {
48 const spirv = try gpa.create(SpirV);52 const spirv = try gpa.create(SpirV);
49 spirv.* = .{53 spirv.* = .{
...@@ -90,9 +94,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -90,9 +94,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
90 return spirv;94 return spirv;
91}95}
9296
93pub fn deinit(self: *SpirV) void {}97pub fn deinit(self: *SpirV) void {
98 self.decl_table.deinit(self.base.allocator);
99}
94100
95pub fn updateDecl(self: *SpirV, module: *Module, decl: *Module.Decl) !void {}101pub fn updateDecl(self: *SpirV, module: *Module, decl: *Module.Decl) !void {
102 // Keep track of all decls so we can iterate over them on flush().
103 _ = try self.decl_table.getOrPut(self.base.allocator, decl);
104}
96105
97pub fn updateDeclExports(106pub fn updateDeclExports(
98 self: *SpirV,107 self: *SpirV,
...@@ -101,7 +110,9 @@ pub fn updateDeclExports(...@@ -101,7 +110,9 @@ pub fn updateDeclExports(
101 exports: []const *Module.Export,110 exports: []const *Module.Export,
102) !void {}111) !void {}
103112
104pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void {}113pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void {
114 self.decl_table.removeAssertDiscard(decl);
115}
105116
106pub fn flush(self: *SpirV, comp: *Compilation) !void {117pub fn flush(self: *SpirV, comp: *Compilation) !void {
107 if (build_options.have_llvm and self.base.options.use_lld) {118 if (build_options.have_llvm and self.base.options.use_lld) {
...@@ -127,10 +138,9 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {...@@ -127,10 +138,9 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {
127 // declarations which don't generate a result?138 // declarations which don't generate a result?
128 // TODO: fn_link is used here, but thats probably not the right field. It will work anyway though.139 // TODO: fn_link is used here, but thats probably not the right field. It will work anyway though.
129 {140 {
130 for (module.decl_table.items()) |entry| {141 for (self.decl_table.items()) |entry| {
131 const decl = entry.value;142 const decl = entry.key;
132 if (decl.typed_value != .most_recent)143 if (!decl.has_tv) continue;
133 continue;
134144
135 decl.fn_link.spirv.id = spv.allocResultId();145 decl.fn_link.spirv.id = spv.allocResultId();
136 log.debug("Allocating id {} to '{s}'", .{ decl.fn_link.spirv.id, std.mem.spanZ(decl.name) });146 log.debug("Allocating id {} to '{s}'", .{ decl.fn_link.spirv.id, std.mem.spanZ(decl.name) });
...@@ -157,10 +167,9 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {...@@ -157,10 +167,9 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {
157 defer decl_gen.types.deinit();167 defer decl_gen.types.deinit();
158 defer decl_gen.args.deinit();168 defer decl_gen.args.deinit();
159169
160 for (module.decl_table.items()) |entry| {170 for (self.decl_table.items()) |entry| {
161 const decl = entry.value;171 const decl = entry.key;
162 if (decl.typed_value != .most_recent)172 if (!decl.has_tv) continue;
163 continue;
164173
165 decl_gen.args.items.len = 0;174 decl_gen.args.items.len = 0;
166 decl_gen.next_arg_index = 0;175 decl_gen.next_arg_index = 0;
...@@ -253,4 +262,4 @@ fn wordsToIovConst(words: []const u32) std.os.iovec_const {...@@ -253,4 +262,4 @@ fn wordsToIovConst(words: []const u32) std.os.iovec_const {
253 .iov_base = bytes.ptr,262 .iov_base = bytes.ptr,
254 .iov_len = bytes.len,263 .iov_len = bytes.len,
255 };264 };
256}
\ No newline at end of file
265}
src/link/Wasm.zig+7-9
...@@ -175,9 +175,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {...@@ -175,9 +175,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
175175
176 self.offset_table.items[block.offset_index] = 0;176 self.offset_table.items[block.offset_index] = 0;
177177
178 const typed_value = decl.typed_value.most_recent.typed_value;178 if (decl.ty.zigTypeTag() == .Fn) {
179 if (typed_value.ty.zigTypeTag() == .Fn) {179 switch (decl.val.tag()) {
180 switch (typed_value.val.tag()) {
181 // dependent on function type, appends it to the correct list180 // dependent on function type, appends it to the correct list
182 .function => try self.funcs.append(self.base.allocator, decl),181 .function => try self.funcs.append(self.base.allocator, decl),
183 .extern_fn => try self.ext_funcs.append(self.base.allocator, decl),182 .extern_fn => try self.ext_funcs.append(self.base.allocator, decl),
...@@ -191,7 +190,6 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {...@@ -191,7 +190,6 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
191pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {190pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
192 std.debug.assert(decl.link.wasm.init); // Must call allocateDeclIndexes()191 std.debug.assert(decl.link.wasm.init); // Must call allocateDeclIndexes()
193192
194 const typed_value = decl.typed_value.most_recent.typed_value;
195 const fn_data = &decl.fn_link.wasm;193 const fn_data = &decl.fn_link.wasm;
196 fn_data.functype.items.len = 0;194 fn_data.functype.items.len = 0;
197 fn_data.code.items.len = 0;195 fn_data.code.items.len = 0;
...@@ -210,7 +208,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {...@@ -210,7 +208,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
210 defer context.deinit();208 defer context.deinit();
211209
212 // generate the 'code' section for the function declaration210 // generate the 'code' section for the function declaration
213 const result = context.gen(typed_value) catch |err| switch (err) {211 const result = context.gen(.{ .ty = decl.ty, .val = decl.val }) catch |err| switch (err) {
214 error.CodegenFail => {212 error.CodegenFail => {
215 decl.analysis = .codegen_failure;213 decl.analysis = .codegen_failure;
216 try module.failed_decls.put(module.gpa, decl, context.err_msg);214 try module.failed_decls.put(module.gpa, decl, context.err_msg);
...@@ -228,7 +226,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {...@@ -228,7 +226,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
228 fn_data.functype = context.func_type_data.toUnmanaged();226 fn_data.functype = context.func_type_data.toUnmanaged();
229227
230 const block = &decl.link.wasm;228 const block = &decl.link.wasm;
231 if (typed_value.ty.zigTypeTag() == .Fn) {229 if (decl.ty.zigTypeTag() == .Fn) {
232 // as locals are patched afterwards, the offsets of funcidx's are off,230 // as locals are patched afterwards, the offsets of funcidx's are off,
233 // here we update them to correct them231 // here we update them to correct them
234 for (fn_data.idx_refs.items) |*func| {232 for (fn_data.idx_refs.items) |*func| {
...@@ -262,7 +260,7 @@ pub fn updateDeclExports(...@@ -262,7 +260,7 @@ pub fn updateDeclExports(
262260
263pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {261pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
264 if (self.getFuncidx(decl)) |func_idx| {262 if (self.getFuncidx(decl)) |func_idx| {
265 switch (decl.typed_value.most_recent.typed_value.val.tag()) {263 switch (decl.val.tag()) {
266 .function => _ = self.funcs.swapRemove(func_idx),264 .function => _ = self.funcs.swapRemove(func_idx),
267 .extern_fn => _ = self.ext_funcs.swapRemove(func_idx),265 .extern_fn => _ = self.ext_funcs.swapRemove(func_idx),
268 else => unreachable,266 else => unreachable,
...@@ -429,7 +427,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {...@@ -429,7 +427,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
429 try leb.writeULEB128(writer, @intCast(u32, exprt.options.name.len));427 try leb.writeULEB128(writer, @intCast(u32, exprt.options.name.len));
430 try writer.writeAll(exprt.options.name);428 try writer.writeAll(exprt.options.name);
431429
432 switch (exprt.exported_decl.typed_value.most_recent.typed_value.ty.zigTypeTag()) {430 switch (exprt.exported_decl.ty.zigTypeTag()) {
433 .Fn => {431 .Fn => {
434 // Type of the export432 // Type of the export
435 try writer.writeByte(wasm.externalKind(.function));433 try writer.writeByte(wasm.externalKind(.function));
...@@ -802,7 +800,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -802,7 +800,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
802/// TODO: we could maintain a hash map to potentially make this simpler800/// TODO: we could maintain a hash map to potentially make this simpler
803fn getFuncidx(self: Wasm, decl: *Module.Decl) ?u32 {801fn getFuncidx(self: Wasm, decl: *Module.Decl) ?u32 {
804 var offset: u32 = 0;802 var offset: u32 = 0;
805 const slice = switch (decl.typed_value.most_recent.typed_value.val.tag()) {803 const slice = switch (decl.val.tag()) {
806 .function => blk: {804 .function => blk: {
807 // when the target is a regular function, we have to calculate805 // when the target is a regular function, we have to calculate
808 // the offset of where the index starts806 // the offset of where the index starts
src/main.zig+516-139
...@@ -12,7 +12,6 @@ const warn = std.log.warn;...@@ -12,7 +12,6 @@ const warn = std.log.warn;
12const Compilation = @import("Compilation.zig");12const Compilation = @import("Compilation.zig");
13const link = @import("link.zig");13const link = @import("link.zig");
14const Package = @import("Package.zig");14const Package = @import("Package.zig");
15const zir = @import("zir.zig");
16const build_options = @import("build_options");15const build_options = @import("build_options");
17const introspect = @import("introspect.zig");16const introspect = @import("introspect.zig");
18const LibCInstallation = @import("libc_installation.zig").LibCInstallation;17const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
...@@ -26,7 +25,11 @@ pub fn fatal(comptime format: []const u8, args: anytype) noreturn {...@@ -26,7 +25,11 @@ pub fn fatal(comptime format: []const u8, args: anytype) noreturn {
26 process.exit(1);25 process.exit(1);
27}26}
2827
29pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB28/// There are many assumptions in the entire codebase that Zig source files can
29/// be byte-indexed with a u32 integer.
30pub const max_src_size = std.math.maxInt(u32);
31
32pub const debug_extensions_enabled = std.builtin.mode == .Debug;
3033
31pub const Color = enum {34pub const Color = enum {
32 auto,35 auto,
...@@ -34,7 +37,7 @@ pub const Color = enum {...@@ -34,7 +37,7 @@ pub const Color = enum {
34 on,37 on,
35};38};
3639
37const usage =40const normal_usage =
38 \\Usage: zig [command] [options]41 \\Usage: zig [command] [options]
39 \\42 \\
40 \\Commands:43 \\Commands:
...@@ -64,6 +67,17 @@ const usage =...@@ -64,6 +67,17 @@ const usage =
64 \\67 \\
65;68;
6669
70const debug_usage = normal_usage ++
71 \\
72 \\Debug Commands:
73 \\
74 \\ astgen Print ZIR code for a .zig source file
75 \\ changelist Compute mappings from old ZIR to new ZIR
76 \\
77;
78
79const usage = if (debug_extensions_enabled) debug_usage else normal_usage;
80
67pub const log_level: std.log.Level = switch (std.builtin.mode) {81pub const log_level: std.log.Level = switch (std.builtin.mode) {
68 .Debug => .debug,82 .Debug => .debug,
69 .ReleaseSafe, .ReleaseFast => .info,83 .ReleaseSafe, .ReleaseFast => .info,
...@@ -107,7 +121,9 @@ pub fn log(...@@ -107,7 +121,9 @@ pub fn log(
107 std.debug.print(prefix1 ++ prefix2 ++ format ++ "\n", args);121 std.debug.print(prefix1 ++ prefix2 ++ format ++ "\n", args);
108}122}
109123
110var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};124var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{
125 .stack_trace_frames = build_options.mem_leak_frames,
126}){};
111127
112pub fn main() anyerror!void {128pub fn main() anyerror!void {
113 const gpa = if (std.builtin.link_libc)129 const gpa = if (std.builtin.link_libc)
...@@ -207,13 +223,17 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v...@@ -207,13 +223,17 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
207 const stdout = io.getStdOut().writer();223 const stdout = io.getStdOut().writer();
208 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, info.target);224 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, info.target);
209 } else if (mem.eql(u8, cmd, "version")) {225 } else if (mem.eql(u8, cmd, "version")) {
210 try std.io.getStdOut().writeAll(build_options.version ++ "\n");226 return std.io.getStdOut().writeAll(build_options.version ++ "\n");
211 } else if (mem.eql(u8, cmd, "env")) {227 } else if (mem.eql(u8, cmd, "env")) {
212 try @import("print_env.zig").cmdEnv(arena, cmd_args, io.getStdOut().writer());228 return @import("print_env.zig").cmdEnv(arena, cmd_args, io.getStdOut().writer());
213 } else if (mem.eql(u8, cmd, "zen")) {229 } else if (mem.eql(u8, cmd, "zen")) {
214 try io.getStdOut().writeAll(info_zen);230 return io.getStdOut().writeAll(info_zen);
215 } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) {231 } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) {
216 try io.getStdOut().writeAll(usage);232 return io.getStdOut().writeAll(usage);
233 } else if (debug_extensions_enabled and mem.eql(u8, cmd, "astgen")) {
234 return cmdAstgen(gpa, arena, cmd_args);
235 } else if (debug_extensions_enabled and mem.eql(u8, cmd, "changelist")) {
236 return cmdChangelist(gpa, arena, cmd_args);
217 } else {237 } else {
218 std.log.info("{s}", .{usage});238 std.log.info("{s}", .{usage});
219 fatal("unknown command: {s}", .{args[1]});239 fatal("unknown command: {s}", .{args[1]});
...@@ -377,9 +397,11 @@ const usage_build_generic =...@@ -377,9 +397,11 @@ const usage_build_generic =
377397
378const repl_help =398const repl_help =
379 \\Commands:399 \\Commands:
380 \\ update Detect changes to source files and update output files.400 \\ update Detect changes to source files and update output files.
381 \\ help Print this text401 \\ run Execute the output file, if it is an executable or test.
382 \\ exit Quit this repl402 \\ update-and-run Perform an `update` followed by `run`.
403 \\ help Print this text
404 \\ exit Quit this repl
383 \\405 \\
384;406;
385407
...@@ -468,18 +490,20 @@ fn optionalStringEnvVar(arena: *Allocator, name: []const u8) !?[]const u8 {...@@ -468,18 +490,20 @@ fn optionalStringEnvVar(arena: *Allocator, name: []const u8) !?[]const u8 {
468 }490 }
469}491}
470492
493const ArgMode = union(enum) {
494 build: std.builtin.OutputMode,
495 cc,
496 cpp,
497 translate_c,
498 zig_test,
499 run,
500};
501
471fn buildOutputType(502fn buildOutputType(
472 gpa: *Allocator,503 gpa: *Allocator,
473 arena: *Allocator,504 arena: *Allocator,
474 all_args: []const []const u8,505 all_args: []const []const u8,
475 arg_mode: union(enum) {506 arg_mode: ArgMode,
476 build: std.builtin.OutputMode,
477 cc,
478 cpp,
479 translate_c,
480 zig_test,
481 run,
482 },
483) !void {507) !void {
484 var color: Color = .auto;508 var color: Color = .auto;
485 var optimize_mode: std.builtin.Mode = .Debug;509 var optimize_mode: std.builtin.Mode = .Debug;
...@@ -606,7 +630,6 @@ fn buildOutputType(...@@ -606,7 +630,6 @@ fn buildOutputType(
606 var pkg_tree_root: Package = .{630 var pkg_tree_root: Package = .{
607 .root_src_directory = .{ .path = null, .handle = fs.cwd() },631 .root_src_directory = .{ .path = null, .handle = fs.cwd() },
608 .root_src_path = &[0]u8{},632 .root_src_path = &[0]u8{},
609 .namespace_hash = Package.root_namespace_hash,
610 };633 };
611 defer freePkgTree(gpa, &pkg_tree_root, false);634 defer freePkgTree(gpa, &pkg_tree_root, false);
612 var cur_pkg: *Package = &pkg_tree_root;635 var cur_pkg: *Package = &pkg_tree_root;
...@@ -1744,7 +1767,6 @@ fn buildOutputType(...@@ -1744,7 +1767,6 @@ fn buildOutputType(
1744 if (root_pkg) |pkg| {1767 if (root_pkg) |pkg| {
1745 pkg.table = pkg_tree_root.table;1768 pkg.table = pkg_tree_root.table;
1746 pkg_tree_root.table = .{};1769 pkg_tree_root.table = .{};
1747 pkg.namespace_hash = pkg_tree_root.namespace_hash;
1748 }1770 }
17491771
1750 const self_exe_path = try fs.selfExePathAlloc(arena);1772 const self_exe_path = try fs.selfExePathAlloc(arena);
...@@ -1954,114 +1976,36 @@ fn buildOutputType(...@@ -1954,114 +1976,36 @@ fn buildOutputType(
1954 .run, .zig_test => true,1976 .run, .zig_test => true,
1955 else => false,1977 else => false,
1956 };1978 };
1957 if (run_or_test) run: {1979 if (run_or_test) {
1958 const exe_loc = emit_bin_loc orelse break :run;1980 try runOrTest(
1959 const exe_directory = exe_loc.directory orelse comp.bin_file.options.emit.?.directory;1981 comp,
1960 const exe_path = try fs.path.join(arena, &[_][]const u8{1982 gpa,
1961 exe_directory.path orelse ".", exe_loc.basename,1983 arena,
1962 });1984 emit_bin_loc,
19631985 test_exec_args.items,
1964 var argv = std.ArrayList([]const u8).init(gpa);1986 self_exe_path,
1965 defer argv.deinit();1987 arg_mode,
19661988 target_info.target,
1967 if (test_exec_args.items.len == 0) {1989 watch,
1968 if (!std.Target.current.canExecBinariesOf(target_info.target)) {1990 &comp_destroyed,
1969 switch (arg_mode) {1991 all_args,
1970 .zig_test => {1992 runtime_args_start,
1971 warn("created {s} but skipping execution because it is non-native", .{exe_path});1993 );
1972 if (!watch) return cleanExit();
1973 break :run;
1974 },
1975 .run => fatal("unable to execute {s}: non-native", .{exe_path}),
1976 else => unreachable,
1977 }
1978 }
1979 // when testing pass the zig_exe_path to argv
1980 if (arg_mode == .zig_test)
1981 try argv.appendSlice(&[_][]const u8{
1982 exe_path, self_exe_path,
1983 })
1984 // when running just pass the current exe
1985 else
1986 try argv.appendSlice(&[_][]const u8{
1987 exe_path,
1988 });
1989 } else {
1990 for (test_exec_args.items) |arg| {
1991 if (arg) |a| {
1992 try argv.append(a);
1993 } else {
1994 try argv.appendSlice(&[_][]const u8{
1995 exe_path, self_exe_path,
1996 });
1997 }
1998 }
1999 }
2000 if (runtime_args_start) |i| {
2001 try argv.appendSlice(all_args[i..]);
2002 }
2003 // We do not execve for tests because if the test fails we want to print
2004 // the error message and invocation below.
2005 if (std.process.can_execv and arg_mode == .run and !watch) {
2006 // execv releases the locks; no need to destroy the Compilation here.
2007 const err = std.process.execv(gpa, argv.items);
2008 const cmd = try argvCmd(arena, argv.items);
2009 fatal("the following command failed to execve with '{s}':\n{s}", .{ @errorName(err), cmd });
2010 } else {
2011 const child = try std.ChildProcess.init(argv.items, gpa);
2012 defer child.deinit();
2013
2014 child.stdin_behavior = .Inherit;
2015 child.stdout_behavior = .Inherit;
2016 child.stderr_behavior = .Inherit;
2017
2018 if (!watch) {
2019 // Here we release all the locks associated with the Compilation so
2020 // that whatever this child process wants to do won't deadlock.
2021 comp.destroy();
2022 comp_destroyed = true;
2023 }
2024
2025 const term = try child.spawnAndWait();
2026 switch (arg_mode) {
2027 .run => {
2028 switch (term) {
2029 .Exited => |code| {
2030 if (code == 0) {
2031 if (!watch) return cleanExit();
2032 } else {
2033 // TODO https://github.com/ziglang/zig/issues/6342
2034 process.exit(1);
2035 }
2036 },
2037 else => process.exit(1),
2038 }
2039 },
2040 .zig_test => {
2041 switch (term) {
2042 .Exited => |code| {
2043 if (code == 0) {
2044 if (!watch) return cleanExit();
2045 } else {
2046 const cmd = try argvCmd(arena, argv.items);
2047 fatal("the following test command failed with exit code {d}:\n{s}", .{ code, cmd });
2048 }
2049 },
2050 else => {
2051 const cmd = try argvCmd(arena, argv.items);
2052 fatal("the following test command crashed:\n{s}", .{cmd});
2053 },
2054 }
2055 },
2056 else => unreachable,
2057 }
2058 }
2059 }1994 }
20601995
2061 const stdin = std.io.getStdIn().reader();1996 const stdin = std.io.getStdIn().reader();
2062 const stderr = std.io.getStdErr().writer();1997 const stderr = std.io.getStdErr().writer();
2063 var repl_buf: [1024]u8 = undefined;1998 var repl_buf: [1024]u8 = undefined;
20641999
2000 const ReplCmd = enum {
2001 update,
2002 help,
2003 run,
2004 update_and_run,
2005 };
2006
2007 var last_cmd: ReplCmd = .help;
2008
2065 while (watch) {2009 while (watch) {
2066 try stderr.print("(zig) ", .{});2010 try stderr.print("(zig) ", .{});
2067 try comp.makeBinFileExecutable();2011 try comp.makeBinFileExecutable();
...@@ -2070,26 +2014,213 @@ fn buildOutputType(...@@ -2070,26 +2014,213 @@ fn buildOutputType(
2070 continue;2014 continue;
2071 }) |line| {2015 }) |line| {
2072 const actual_line = mem.trimRight(u8, line, "\r\n ");2016 const actual_line = mem.trimRight(u8, line, "\r\n ");
20732017 const cmd: ReplCmd = blk: {
2074 if (mem.eql(u8, actual_line, "update")) {2018 if (mem.eql(u8, actual_line, "update")) {
2075 if (output_mode == .Exe) {2019 break :blk .update;
2076 try comp.makeBinFileWritable();2020 } else if (mem.eql(u8, actual_line, "exit")) {
2021 break;
2022 } else if (mem.eql(u8, actual_line, "help")) {
2023 break :blk .help;
2024 } else if (mem.eql(u8, actual_line, "run")) {
2025 break :blk .run;
2026 } else if (mem.eql(u8, actual_line, "update-and-run")) {
2027 break :blk .update_and_run;
2028 } else if (actual_line.len == 0) {
2029 break :blk last_cmd;
2030 } else {
2031 try stderr.print("unknown command: {s}\n", .{actual_line});
2032 continue;
2077 }2033 }
2078 updateModule(gpa, comp, hook) catch |err| switch (err) {2034 };
2079 error.SemanticAnalyzeFail => continue,2035 last_cmd = cmd;
2080 else => |e| return e,2036 switch (cmd) {
2081 };2037 .update => {
2082 } else if (mem.eql(u8, actual_line, "exit")) {2038 if (output_mode == .Exe) {
2083 break;2039 try comp.makeBinFileWritable();
2084 } else if (mem.eql(u8, actual_line, "help")) {2040 }
2085 try stderr.writeAll(repl_help);2041 updateModule(gpa, comp, hook) catch |err| switch (err) {
2086 } else {2042 error.SemanticAnalyzeFail => continue,
2087 try stderr.print("unknown command: {s}\n", .{actual_line});2043 else => |e| return e,
2044 };
2045 },
2046 .help => {
2047 try stderr.writeAll(repl_help);
2048 },
2049 .run => {
2050 try runOrTest(
2051 comp,
2052 gpa,
2053 arena,
2054 emit_bin_loc,
2055 test_exec_args.items,
2056 self_exe_path,
2057 arg_mode,
2058 target_info.target,
2059 watch,
2060 &comp_destroyed,
2061 all_args,
2062 runtime_args_start,
2063 );
2064 },
2065 .update_and_run => {
2066 if (output_mode == .Exe) {
2067 try comp.makeBinFileWritable();
2068 }
2069 updateModule(gpa, comp, hook) catch |err| switch (err) {
2070 error.SemanticAnalyzeFail => continue,
2071 else => |e| return e,
2072 };
2073 try comp.makeBinFileExecutable();
2074 try runOrTest(
2075 comp,
2076 gpa,
2077 arena,
2078 emit_bin_loc,
2079 test_exec_args.items,
2080 self_exe_path,
2081 arg_mode,
2082 target_info.target,
2083 watch,
2084 &comp_destroyed,
2085 all_args,
2086 runtime_args_start,
2087 );
2088 },
2088 }2089 }
2089 } else {2090 } else {
2090 break;2091 break;
2091 }2092 }
2092 }2093 }
2094 // Skip resource deallocation in release builds; let the OS do it.
2095 return cleanExit();
2096}
2097
2098fn runOrTest(
2099 comp: *Compilation,
2100 gpa: *Allocator,
2101 arena: *Allocator,
2102 emit_bin_loc: ?Compilation.EmitLoc,
2103 test_exec_args: []const ?[]const u8,
2104 self_exe_path: []const u8,
2105 arg_mode: ArgMode,
2106 target: std.Target,
2107 watch: bool,
2108 comp_destroyed: *bool,
2109 all_args: []const []const u8,
2110 runtime_args_start: ?usize,
2111) !void {
2112 const exe_loc = emit_bin_loc orelse return;
2113 const exe_directory = exe_loc.directory orelse comp.bin_file.options.emit.?.directory;
2114 const exe_path = try fs.path.join(arena, &[_][]const u8{
2115 exe_directory.path orelse ".", exe_loc.basename,
2116 });
2117
2118 var argv = std.ArrayList([]const u8).init(gpa);
2119 defer argv.deinit();
2120
2121 if (test_exec_args.len == 0) {
2122 if (!std.Target.current.canExecBinariesOf(target)) {
2123 switch (arg_mode) {
2124 .zig_test => {
2125 warn("created {s} but skipping execution because it is non-native", .{exe_path});
2126 if (!watch) return cleanExit();
2127 return;
2128 },
2129 else => {
2130 std.log.err("unable to execute {s}: non-native", .{exe_path});
2131 if (!watch) process.exit(1);
2132 return;
2133 },
2134 }
2135 }
2136 // when testing pass the zig_exe_path to argv
2137 if (arg_mode == .zig_test)
2138 try argv.appendSlice(&[_][]const u8{
2139 exe_path, self_exe_path,
2140 })
2141 // when running just pass the current exe
2142 else
2143 try argv.appendSlice(&[_][]const u8{
2144 exe_path,
2145 });
2146 } else {
2147 for (test_exec_args) |arg| {
2148 if (arg) |a| {
2149 try argv.append(a);
2150 } else {
2151 try argv.appendSlice(&[_][]const u8{
2152 exe_path, self_exe_path,
2153 });
2154 }
2155 }
2156 }
2157 if (runtime_args_start) |i| {
2158 try argv.appendSlice(all_args[i..]);
2159 }
2160 // We do not execve for tests because if the test fails we want to print
2161 // the error message and invocation below.
2162 if (std.process.can_execv and arg_mode == .run and !watch) {
2163 // execv releases the locks; no need to destroy the Compilation here.
2164 const err = std.process.execv(gpa, argv.items);
2165 const cmd = try argvCmd(arena, argv.items);
2166 fatal("the following command failed to execve with '{s}':\n{s}", .{ @errorName(err), cmd });
2167 } else {
2168 const child = try std.ChildProcess.init(argv.items, gpa);
2169 defer child.deinit();
2170
2171 child.stdin_behavior = .Inherit;
2172 child.stdout_behavior = .Inherit;
2173 child.stderr_behavior = .Inherit;
2174
2175 if (!watch) {
2176 // Here we release all the locks associated with the Compilation so
2177 // that whatever this child process wants to do won't deadlock.
2178 comp.destroy();
2179 comp_destroyed.* = true;
2180 }
2181
2182 const term = try child.spawnAndWait();
2183 switch (arg_mode) {
2184 .run, .build => {
2185 switch (term) {
2186 .Exited => |code| {
2187 if (code == 0) {
2188 if (!watch) return cleanExit();
2189 } else if (watch) {
2190 warn("process exited with code {d}", .{code});
2191 } else {
2192 // TODO https://github.com/ziglang/zig/issues/6342
2193 process.exit(1);
2194 }
2195 },
2196 else => {
2197 if (watch) {
2198 warn("process aborted abnormally", .{});
2199 } else {
2200 process.exit(1);
2201 }
2202 },
2203 }
2204 },
2205 .zig_test => {
2206 switch (term) {
2207 .Exited => |code| {
2208 if (code == 0) {
2209 if (!watch) return cleanExit();
2210 } else {
2211 const cmd = try argvCmd(arena, argv.items);
2212 fatal("the following test command failed with exit code {d}:\n{s}", .{ code, cmd });
2213 }
2214 },
2215 else => {
2216 const cmd = try argvCmd(arena, argv.items);
2217 fatal("the following test command crashed:\n{s}", .{cmd});
2218 },
2219 }
2220 },
2221 else => unreachable,
2222 }
2223 }
2093}2224}
20942225
2095const AfterUpdateHook = union(enum) {2226const AfterUpdateHook = union(enum) {
...@@ -2524,7 +2655,6 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v...@@ -2524,7 +2655,6 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
2524 .handle = try zig_lib_directory.handle.openDir(std_special, .{}),2655 .handle = try zig_lib_directory.handle.openDir(std_special, .{}),
2525 },2656 },
2526 .root_src_path = "build_runner.zig",2657 .root_src_path = "build_runner.zig",
2527 .namespace_hash = Package.root_namespace_hash,
2528 };2658 };
2529 defer root_pkg.root_src_directory.handle.close();2659 defer root_pkg.root_src_directory.handle.close();
25302660
...@@ -2570,7 +2700,6 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v...@@ -2570,7 +2700,6 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
2570 var build_pkg: Package = .{2700 var build_pkg: Package = .{
2571 .root_src_directory = build_directory,2701 .root_src_directory = build_directory,
2572 .root_src_path = build_zig_basename,2702 .root_src_path = build_zig_basename,
2573 .namespace_hash = undefined,
2574 };2703 };
2575 try root_pkg.addAndAdopt(arena, "@build", &build_pkg);2704 try root_pkg.addAndAdopt(arena, "@build", &build_pkg);
25762705
...@@ -3423,3 +3552,251 @@ pub fn cleanExit() void {...@@ -3423,3 +3552,251 @@ pub fn cleanExit() void {
3423 process.exit(0);3552 process.exit(0);
3424 }3553 }
3425}3554}
3555
3556/// This is only enabled for debug builds.
3557pub fn cmdAstgen(
3558 gpa: *Allocator,
3559 arena: *Allocator,
3560 args: []const []const u8,
3561) !void {
3562 const Module = @import("Module.zig");
3563 const AstGen = @import("AstGen.zig");
3564 const Zir = @import("Zir.zig");
3565
3566 const zig_source_file = args[0];
3567
3568 var f = try fs.cwd().openFile(zig_source_file, .{});
3569 defer f.close();
3570
3571 const stat = try f.stat();
3572
3573 if (stat.size > max_src_size)
3574 return error.FileTooBig;
3575
3576 var file: Module.Scope.File = .{
3577 .status = .never_loaded,
3578 .source_loaded = false,
3579 .tree_loaded = false,
3580 .zir_loaded = false,
3581 .sub_file_path = zig_source_file,
3582 .source = undefined,
3583 .stat_size = stat.size,
3584 .stat_inode = stat.inode,
3585 .stat_mtime = stat.mtime,
3586 .tree = undefined,
3587 .zir = undefined,
3588 .pkg = undefined,
3589 .root_decl = null,
3590 };
3591
3592 const source = try arena.allocSentinel(u8, stat.size, 0);
3593 const amt = try f.readAll(source);
3594 if (amt != stat.size)
3595 return error.UnexpectedEndOfFile;
3596 file.source = source;
3597 file.source_loaded = true;
3598
3599 file.tree = try std.zig.parse(gpa, file.source);
3600 file.tree_loaded = true;
3601 defer file.tree.deinit(gpa);
3602
3603 for (file.tree.errors) |parse_error| {
3604 try printErrMsgToFile(gpa, parse_error, file.tree, zig_source_file, io.getStdErr(), .auto);
3605 }
3606 if (file.tree.errors.len != 0) {
3607 process.exit(1);
3608 }
3609
3610 file.zir = try AstGen.generate(gpa, file.tree);
3611 file.zir_loaded = true;
3612 defer file.zir.deinit(gpa);
3613
3614 {
3615 const token_bytes = @sizeOf(std.zig.ast.TokenList) +
3616 file.tree.tokens.len * (@sizeOf(std.zig.Token.Tag) + @sizeOf(std.zig.ast.ByteOffset));
3617 const tree_bytes = @sizeOf(std.zig.ast.Tree) + file.tree.nodes.len *
3618 (@sizeOf(std.zig.ast.Node.Tag) +
3619 @sizeOf(std.zig.ast.Node.Data) +
3620 @sizeOf(std.zig.ast.TokenIndex));
3621 const instruction_bytes = file.zir.instructions.len *
3622 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include
3623 // the debug safety tag but we want to measure release size.
3624 (@sizeOf(Zir.Inst.Tag) + 8);
3625 const extra_bytes = file.zir.extra.len * @sizeOf(u32);
3626 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
3627 file.zir.string_bytes.len * @sizeOf(u8);
3628 const stdout = io.getStdOut();
3629 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
3630 // zig fmt: off
3631 try stdout.writer().print(
3632 \\# Source bytes: {}
3633 \\# Tokens: {} ({})
3634 \\# AST Nodes: {} ({})
3635 \\# Total ZIR bytes: {}
3636 \\# Instructions: {d} ({})
3637 \\# String Table Bytes: {}
3638 \\# Extra Data Items: {d} ({})
3639 \\
3640 , .{
3641 fmtIntSizeBin(source.len),
3642 file.tree.tokens.len, fmtIntSizeBin(token_bytes),
3643 file.tree.nodes.len, fmtIntSizeBin(tree_bytes),
3644 fmtIntSizeBin(total_bytes),
3645 file.zir.instructions.len, fmtIntSizeBin(instruction_bytes),
3646 fmtIntSizeBin(file.zir.string_bytes.len),
3647 file.zir.extra.len, fmtIntSizeBin(extra_bytes),
3648 });
3649 // zig fmt: on
3650 }
3651
3652 if (file.zir.hasCompileErrors()) {
3653 var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena);
3654 try Compilation.AllErrors.addZir(arena, &errors, &file);
3655 const ttyconf = std.debug.detectTTYConfig();
3656 for (errors.items) |full_err_msg| {
3657 full_err_msg.renderToStdErr(ttyconf);
3658 }
3659 process.exit(1);
3660 }
3661
3662 return Zir.renderAsTextToFile(gpa, &file, io.getStdOut());
3663}
3664
3665/// This is only enabled for debug builds.
3666pub fn cmdChangelist(
3667 gpa: *Allocator,
3668 arena: *Allocator,
3669 args: []const []const u8,
3670) !void {
3671 const Module = @import("Module.zig");
3672 const AstGen = @import("AstGen.zig");
3673 const Zir = @import("Zir.zig");
3674
3675 const old_source_file = args[0];
3676 const new_source_file = args[1];
3677
3678 var f = try fs.cwd().openFile(old_source_file, .{});
3679 defer f.close();
3680
3681 const stat = try f.stat();
3682
3683 if (stat.size > max_src_size)
3684 return error.FileTooBig;
3685
3686 var file: Module.Scope.File = .{
3687 .status = .never_loaded,
3688 .source_loaded = false,
3689 .tree_loaded = false,
3690 .zir_loaded = false,
3691 .sub_file_path = old_source_file,
3692 .source = undefined,
3693 .stat_size = stat.size,
3694 .stat_inode = stat.inode,
3695 .stat_mtime = stat.mtime,
3696 .tree = undefined,
3697 .zir = undefined,
3698 .pkg = undefined,
3699 .root_decl = null,
3700 };
3701
3702 const source = try arena.allocSentinel(u8, stat.size, 0);
3703 const amt = try f.readAll(source);
3704 if (amt != stat.size)
3705 return error.UnexpectedEndOfFile;
3706 file.source = source;
3707 file.source_loaded = true;
3708
3709 file.tree = try std.zig.parse(gpa, file.source);
3710 file.tree_loaded = true;
3711 defer file.tree.deinit(gpa);
3712
3713 for (file.tree.errors) |parse_error| {
3714 try printErrMsgToFile(gpa, parse_error, file.tree, old_source_file, io.getStdErr(), .auto);
3715 }
3716 if (file.tree.errors.len != 0) {
3717 process.exit(1);
3718 }
3719
3720 file.zir = try AstGen.generate(gpa, file.tree);
3721 file.zir_loaded = true;
3722 defer file.zir.deinit(gpa);
3723
3724 if (file.zir.hasCompileErrors()) {
3725 var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena);
3726 try Compilation.AllErrors.addZir(arena, &errors, &file);
3727 const ttyconf = std.debug.detectTTYConfig();
3728 for (errors.items) |full_err_msg| {
3729 full_err_msg.renderToStdErr(ttyconf);
3730 }
3731 process.exit(1);
3732 }
3733
3734 var new_f = try fs.cwd().openFile(new_source_file, .{});
3735 defer new_f.close();
3736
3737 const new_stat = try new_f.stat();
3738
3739 if (new_stat.size > max_src_size)
3740 return error.FileTooBig;
3741
3742 const new_source = try arena.allocSentinel(u8, new_stat.size, 0);
3743 const new_amt = try new_f.readAll(new_source);
3744 if (new_amt != new_stat.size)
3745 return error.UnexpectedEndOfFile;
3746
3747 var new_tree = try std.zig.parse(gpa, new_source);
3748 defer new_tree.deinit(gpa);
3749
3750 for (new_tree.errors) |parse_error| {
3751 try printErrMsgToFile(gpa, parse_error, new_tree, new_source_file, io.getStdErr(), .auto);
3752 }
3753 if (new_tree.errors.len != 0) {
3754 process.exit(1);
3755 }
3756
3757 var old_zir = file.zir;
3758 defer old_zir.deinit(gpa);
3759 file.zir_loaded = false;
3760 file.zir = try AstGen.generate(gpa, new_tree);
3761 file.zir_loaded = true;
3762
3763 if (file.zir.hasCompileErrors()) {
3764 var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena);
3765 try Compilation.AllErrors.addZir(arena, &errors, &file);
3766 const ttyconf = std.debug.detectTTYConfig();
3767 for (errors.items) |full_err_msg| {
3768 full_err_msg.renderToStdErr(ttyconf);
3769 }
3770 process.exit(1);
3771 }
3772
3773 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};
3774 defer inst_map.deinit(gpa);
3775
3776 var extra_map: std.AutoHashMapUnmanaged(u32, u32) = .{};
3777 defer extra_map.deinit(gpa);
3778
3779 try Module.mapOldZirToNew(gpa, old_zir, file.zir, &inst_map, &extra_map);
3780
3781 var bw = io.bufferedWriter(io.getStdOut().writer());
3782 const stdout = bw.writer();
3783 {
3784 try stdout.print("Instruction mappings:\n", .{});
3785 var it = inst_map.iterator();
3786 while (it.next()) |entry| {
3787 try stdout.print(" %{d} => %{d}\n", .{
3788 entry.key, entry.value,
3789 });
3790 }
3791 }
3792 {
3793 try stdout.print("Extra mappings:\n", .{});
3794 var it = extra_map.iterator();
3795 while (it.next()) |entry| {
3796 try stdout.print(" {d} => {d}\n", .{
3797 entry.key, entry.value,
3798 });
3799 }
3800 }
3801 try bw.flush();
3802}
src/stage1/codegen.cpp+24-18
...@@ -8931,10 +8931,10 @@ static const char *bool_to_str(bool b) {...@@ -8931,10 +8931,10 @@ static const char *bool_to_str(bool b) {
89318931
8932static const char *build_mode_to_str(BuildMode build_mode) {8932static const char *build_mode_to_str(BuildMode build_mode) {
8933 switch (build_mode) {8933 switch (build_mode) {
8934 case BuildModeDebug: return "Mode.Debug";8934 case BuildModeDebug: return "Debug";
8935 case BuildModeSafeRelease: return "Mode.ReleaseSafe";8935 case BuildModeSafeRelease: return "ReleaseSafe";
8936 case BuildModeFastRelease: return "Mode.ReleaseFast";8936 case BuildModeFastRelease: return "ReleaseFast";
8937 case BuildModeSmallRelease: return "Mode.ReleaseSmall";8937 case BuildModeSmallRelease: return "ReleaseSmall";
8938 }8938 }
8939 zig_unreachable();8939 zig_unreachable();
8940}8940}
...@@ -9005,7 +9005,9 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -9005,7 +9005,9 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
9005 g->have_err_ret_tracing = detect_err_ret_tracing(g);9005 g->have_err_ret_tracing = detect_err_ret_tracing(g);
90069006
9007 Buf *contents = buf_alloc();9007 Buf *contents = buf_alloc();
9008 buf_appendf(contents, "usingnamespace @import(\"std\").builtin;\n\n");9008 buf_appendf(contents,
9009 "const std = @import(\"std\");\n"
9010 );
90099011
9010 const char *cur_os = nullptr;9012 const char *cur_os = nullptr;
9011 {9013 {
...@@ -9100,19 +9102,23 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -9100,19 +9102,23 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
9100 static_assert(TargetSubsystemEfiRom == 6, "");9102 static_assert(TargetSubsystemEfiRom == 6, "");
9101 static_assert(TargetSubsystemEfiRuntimeDriver == 7, "");9103 static_assert(TargetSubsystemEfiRuntimeDriver == 7, "");
91029104
9103 buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch`\n");9105 buf_appendf(contents, "pub const output_mode = std.builtin.OutputMode.Obj;\n");
9104 buf_append_str(contents, "pub const arch = Target.current.cpu.arch;\n");9106 buf_appendf(contents, "pub const link_mode = std.builtin.LinkMode.%s;\n", ZIG_QUOTE(ZIG_LINK_MODE));
9105 buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch.endian()`\n");
9106 buf_append_str(contents, "pub const endian = Target.current.cpu.arch.endian();\n");
9107 buf_appendf(contents, "pub const output_mode = OutputMode.Obj;\n");
9108 buf_appendf(contents, "pub const link_mode = LinkMode.%s;\n", ZIG_QUOTE(ZIG_LINK_MODE));
9109 buf_appendf(contents, "pub const is_test = false;\n");9107 buf_appendf(contents, "pub const is_test = false;\n");
9110 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));9108 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
9111 buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);9109 buf_appendf(contents, "pub const abi = std.Target.Abi.%s;\n", cur_abi);
9112 buf_appendf(contents, "pub const cpu: Cpu = Target.Cpu.baseline(.%s);\n", cur_arch);9110 buf_appendf(contents, "pub const cpu = std.Target.Cpu.baseline(.%s);\n", cur_arch);
9113 buf_appendf(contents, "pub const os = Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os);9111 buf_appendf(contents, "pub const os = std.Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os);
9114 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);9112 buf_appendf(contents,
9115 buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));9113 "pub const target = std.Target{\n"
9114 " .cpu = cpu,\n"
9115 " .os = os,\n"
9116 " .abi = abi,\n"
9117 "};\n"
9118 );
9119
9120 buf_appendf(contents, "pub const object_format = std.Target.ObjectFormat.%s;\n", cur_obj_fmt);
9121 buf_appendf(contents, "pub const mode = std.builtin.Mode.%s;\n", build_mode_to_str(g->build_mode));
9116 buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->link_libc));9122 buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->link_libc));
9117 buf_appendf(contents, "pub const link_libcpp = %s;\n", bool_to_str(g->link_libcpp));9123 buf_appendf(contents, "pub const link_libcpp = %s;\n", bool_to_str(g->link_libcpp));
9118 buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));9124 buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
...@@ -9120,13 +9126,13 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -9120,13 +9126,13 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
9120 buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));9126 buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
9121 buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie));9127 buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie));
9122 buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));9128 buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));
9123 buf_appendf(contents, "pub const code_model = CodeModel.default;\n");9129 buf_appendf(contents, "pub const code_model = std.builtin.CodeModel.default;\n");
9124 buf_appendf(contents, "pub const zig_is_stage2 = false;\n");9130 buf_appendf(contents, "pub const zig_is_stage2 = false;\n");
91259131
9126 {9132 {
9127 TargetSubsystem detected_subsystem = detect_subsystem(g);9133 TargetSubsystem detected_subsystem = detect_subsystem(g);
9128 if (detected_subsystem != TargetSubsystemAuto) {9134 if (detected_subsystem != TargetSubsystemAuto) {
9129 buf_appendf(contents, "pub const explicit_subsystem = SubSystem.%s;\n", subsystem_to_str(detected_subsystem));9135 buf_appendf(contents, "pub const explicit_subsystem = std.builtin.SubSystem.%s;\n", subsystem_to_str(detected_subsystem));
9130 }9136 }
9131 }9137 }
91329138
src/stage1/ir.cpp+7-16
...@@ -30541,22 +30541,13 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -30541,22 +30541,13 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
30541 case ZigTypeIdVector:30541 case ZigTypeIdVector:
30542 return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.vector.elem_type,30542 return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.vector.elem_type,
30543 val->type->data.vector.len);30543 val->type->data.vector.len);
30544 case ZigTypeIdEnum:30544 case ZigTypeIdEnum: {
30545 switch (val->type->data.enumeration.layout) {30545 ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;
30546 case ContainerLayoutAuto:30546 src_assert(tag_int_type->id == ZigTypeIdInt, source_node);
30547 zig_panic("TODO buf_read_value_bytes enum auto");30547 bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,
30548 case ContainerLayoutPacked:30548 codegen->is_big_endian, tag_int_type->data.integral.is_signed);
30549 zig_panic("TODO buf_read_value_bytes enum packed");30549 return ErrorNone;
30550 case ContainerLayoutExtern: {30550 } case ZigTypeIdStruct:
30551 ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;
30552 src_assert(tag_int_type->id == ZigTypeIdInt, source_node);
30553 bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,
30554 codegen->is_big_endian, tag_int_type->data.integral.is_signed);
30555 return ErrorNone;
30556 }
30557 }
30558 zig_unreachable();
30559 case ZigTypeIdStruct:
30560 switch (val->type->data.structure.layout) {30551 switch (val->type->data.structure.layout) {
30561 case ContainerLayoutAuto: {30552 case ContainerLayoutAuto: {
30562 switch(val->type->data.structure.special){30553 switch(val->type->data.structure.special){
src/test.zig+22-131
...@@ -2,7 +2,6 @@ const std = @import("std");...@@ -2,7 +2,6 @@ const std = @import("std");
2const link = @import("link.zig");2const link = @import("link.zig");
3const Compilation = @import("Compilation.zig");3const Compilation = @import("Compilation.zig");
4const Allocator = std.mem.Allocator;4const Allocator = std.mem.Allocator;
5const zir = @import("zir.zig");
6const Package = @import("Package.zig");5const Package = @import("Package.zig");
7const introspect = @import("introspect.zig");6const introspect = @import("introspect.zig");
8const build_options = @import("build_options");7const build_options = @import("build_options");
...@@ -16,7 +15,7 @@ const CrossTarget = std.zig.CrossTarget;...@@ -16,7 +15,7 @@ const CrossTarget = std.zig.CrossTarget;
1615
17const zig_h = link.File.C.zig_h;16const zig_h = link.File.C.zig_h;
1817
19const hr = "=" ** 40;18const hr = "=" ** 80;
2019
21test "self-hosted" {20test "self-hosted" {
22 var ctx = TestContext.init();21 var ctx = TestContext.init();
...@@ -137,7 +136,7 @@ pub const TestContext = struct {...@@ -137,7 +136,7 @@ pub const TestContext = struct {
137 /// to Executable.136 /// to Executable.
138 output_mode: std.builtin.OutputMode,137 output_mode: std.builtin.OutputMode,
139 updates: std.ArrayList(Update),138 updates: std.ArrayList(Update),
140 object_format: ?std.builtin.ObjectFormat = null,139 object_format: ?std.Target.ObjectFormat = null,
141 emit_h: bool = false,140 emit_h: bool = false,
142 llvm_backend: bool = false,141 llvm_backend: bool = false,
143142
...@@ -543,6 +542,8 @@ pub const TestContext = struct {...@@ -543,6 +542,8 @@ pub const TestContext = struct {
543 };542 };
544 defer std.testing.allocator.free(global_cache_directory.path.?);543 defer std.testing.allocator.free(global_cache_directory.path.?);
545544
545 var fail_count: usize = 0;
546
546 for (self.cases.items) |case| {547 for (self.cases.items) |case| {
547 if (build_options.skip_non_native and case.target.getCpuArch() != std.Target.current.cpu.arch)548 if (build_options.skip_non_native and case.target.getCpuArch() != std.Target.current.cpu.arch)
548 continue;549 continue;
...@@ -560,14 +561,21 @@ pub const TestContext = struct {...@@ -560,14 +561,21 @@ pub const TestContext = struct {
560 progress.initial_delay_ns = 0;561 progress.initial_delay_ns = 0;
561 progress.refresh_rate_ns = 0;562 progress.refresh_rate_ns = 0;
562563
563 try self.runOneCase(564 self.runOneCase(
564 std.testing.allocator,565 std.testing.allocator,
565 &prg_node,566 &prg_node,
566 case,567 case,
567 zig_lib_directory,568 zig_lib_directory,
568 &thread_pool,569 &thread_pool,
569 global_cache_directory,570 global_cache_directory,
570 );571 ) catch |err| {
572 fail_count += 1;
573 std.debug.print("test '{s}' failed: {s}\n\n", .{ case.name, @errorName(err) });
574 };
575 }
576 if (fail_count != 0) {
577 std.debug.print("{d} tests failed\n", .{fail_count});
578 return error.TestFailed;
571 }579 }
572 }580 }
573581
...@@ -603,7 +611,6 @@ pub const TestContext = struct {...@@ -603,7 +611,6 @@ pub const TestContext = struct {
603 var root_pkg: Package = .{611 var root_pkg: Package = .{
604 .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir },612 .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir },
605 .root_src_path = tmp_src_path,613 .root_src_path = tmp_src_path,
606 .namespace_hash = Package.root_namespace_hash,
607 };614 };
608 defer root_pkg.table.deinit(allocator);615 defer root_pkg.table.deinit(allocator);
609616
...@@ -695,8 +702,7 @@ pub const TestContext = struct {...@@ -695,8 +702,7 @@ pub const TestContext = struct {
695 }702 }
696 }703 }
697 // TODO print generated C code704 // TODO print generated C code
698 std.debug.print("Test failed.\n", .{});705 return error.UnexpectedCompileErrors;
699 std.process.exit(1);
700 }706 }
701 }707 }
702708
...@@ -819,10 +825,8 @@ pub const TestContext = struct {...@@ -819,10 +825,8 @@ pub const TestContext = struct {
819 }825 }
820826
821 if (any_failed) {827 if (any_failed) {
822 std.debug.print("\nTest case '{s}' failed, update_index={d}.\n", .{828 std.debug.print("\nupdate_index={d} ", .{update_index});
823 case.name, update_index,829 return error.WrongCompileErrors;
824 });
825 std.process.exit(1);
826 }830 }
827 },831 },
828 .Execution => |expected_stdout| {832 .Execution => |expected_stdout| {
...@@ -858,10 +862,7 @@ pub const TestContext = struct {...@@ -858,10 +862,7 @@ pub const TestContext = struct {
858 });862 });
859 } else switch (case.target.getExternalExecutor()) {863 } else switch (case.target.getExternalExecutor()) {
860 .native => try argv.append(exe_path),864 .native => try argv.append(exe_path),
861 .unavailable => {865 .unavailable => return, // Pass test.
862 try self.runInterpreterIfAvailable(allocator, &exec_node, case, tmp.dir, bin_name);
863 return; // Pass test.
864 },
865866
866 .qemu => |qemu_bin_name| if (enable_qemu) {867 .qemu => |qemu_bin_name| if (enable_qemu) {
867 // TODO Ability for test cases to specify whether to link libc.868 // TODO Ability for test cases to specify whether to link libc.
...@@ -920,11 +921,11 @@ pub const TestContext = struct {...@@ -920,11 +921,11 @@ pub const TestContext = struct {
920 .cwd_dir = tmp.dir,921 .cwd_dir = tmp.dir,
921 .cwd = tmp_dir_path,922 .cwd = tmp_dir_path,
922 }) catch |err| {923 }) catch |err| {
923 std.debug.print("\nThe following command failed with {s}:\n", .{924 std.debug.print("\nupdate_index={d} The following command failed with {s}:\n", .{
924 @errorName(err),925 update_index, @errorName(err),
925 });926 });
926 dumpArgs(argv.items);927 dumpArgs(argv.items);
927 return error.ZigTestFailed;928 return error.ChildProcessExecution;
928 };929 };
929 };930 };
930 var test_node = update_node.start("test", 0);931 var test_node = update_node.start("test", 0);
...@@ -939,7 +940,7 @@ pub const TestContext = struct {...@@ -939,7 +940,7 @@ pub const TestContext = struct {
939 exec_result.stderr, case.name, code,940 exec_result.stderr, case.name, code,
940 });941 });
941 dumpArgs(argv.items);942 dumpArgs(argv.items);
942 return error.ZigTestFailed;943 return error.ChildProcessExecution;
943 }944 }
944 },945 },
945 else => {946 else => {
...@@ -947,7 +948,7 @@ pub const TestContext = struct {...@@ -947,7 +948,7 @@ pub const TestContext = struct {
947 exec_result.stderr, case.name,948 exec_result.stderr, case.name,
948 });949 });
949 dumpArgs(argv.items);950 dumpArgs(argv.items);
950 return error.ZigTestFailed;951 return error.ChildProcessExecution;
951 },952 },
952 }953 }
953 try std.testing.expectEqualStrings(expected_stdout, exec_result.stdout);954 try std.testing.expectEqualStrings(expected_stdout, exec_result.stdout);
...@@ -959,116 +960,6 @@ pub const TestContext = struct {...@@ -959,116 +960,6 @@ pub const TestContext = struct {
959 }960 }
960 }961 }
961962
962 fn runInterpreterIfAvailable(
963 self: *TestContext,
964 gpa: *Allocator,
965 node: *std.Progress.Node,
966 case: Case,
967 tmp_dir: std.fs.Dir,
968 bin_name: []const u8,
969 ) !void {
970 const arch = case.target.cpu_arch orelse return;
971 switch (arch) {
972 .spu_2 => return self.runSpu2Interpreter(gpa, node, case, tmp_dir, bin_name),
973 else => return,
974 }
975 }
976
977 fn runSpu2Interpreter(
978 self: *TestContext,
979 gpa: *Allocator,
980 update_node: *std.Progress.Node,
981 case: Case,
982 tmp_dir: std.fs.Dir,
983 bin_name: []const u8,
984 ) !void {
985 const spu = @import("codegen/spu-mk2.zig");
986 if (case.target.os_tag) |os| {
987 if (os != .freestanding) {
988 std.debug.panic("Only freestanding makes sense for SPU-II tests!", .{});
989 }
990 } else {
991 std.debug.panic("SPU_2 has no native OS, check the test!", .{});
992 }
993
994 var interpreter = spu.Interpreter(struct {
995 RAM: [0x10000]u8 = undefined,
996
997 pub fn read8(bus: @This(), addr: u16) u8 {
998 return bus.RAM[addr];
999 }
1000 pub fn read16(bus: @This(), addr: u16) u16 {
1001 return std.mem.readIntLittle(u16, bus.RAM[addr..][0..2]);
1002 }
1003
1004 pub fn write8(bus: *@This(), addr: u16, val: u8) void {
1005 bus.RAM[addr] = val;
1006 }
1007
1008 pub fn write16(bus: *@This(), addr: u16, val: u16) void {
1009 std.mem.writeIntLittle(u16, bus.RAM[addr..][0..2], val);
1010 }
1011 }){
1012 .bus = .{},
1013 };
1014
1015 {
1016 var load_node = update_node.start("load", 0);
1017 load_node.activate();
1018 defer load_node.end();
1019
1020 var file = try tmp_dir.openFile(bin_name, .{ .read = true });
1021 defer file.close();
1022
1023 const header = try std.elf.Header.read(&file);
1024 var iterator = header.program_header_iterator(&file);
1025
1026 var none_loaded = true;
1027
1028 while (try iterator.next()) |phdr| {
1029 if (phdr.p_type != std.elf.PT_LOAD) {
1030 std.debug.print("Encountered unexpected ELF program header: type {}\n", .{phdr.p_type});
1031 std.process.exit(1);
1032 }
1033 if (phdr.p_paddr != phdr.p_vaddr) {
1034 std.debug.print("Physical address does not match virtual address in ELF header!\n", .{});
1035 std.process.exit(1);
1036 }
1037 if (phdr.p_filesz != phdr.p_memsz) {
1038 std.debug.print("Physical size does not match virtual size in ELF header!\n", .{});
1039 std.process.exit(1);
1040 }
1041 if ((try file.pread(interpreter.bus.RAM[phdr.p_paddr .. phdr.p_paddr + phdr.p_filesz], phdr.p_offset)) != phdr.p_filesz) {
1042 std.debug.print("Read less than expected from ELF file!", .{});
1043 std.process.exit(1);
1044 }
1045 std.log.scoped(.spu2_test).debug("Loaded 0x{x} bytes to 0x{x:0<4}\n", .{ phdr.p_filesz, phdr.p_paddr });
1046 none_loaded = false;
1047 }
1048 if (none_loaded) {
1049 std.debug.print("No data found in ELF file!\n", .{});
1050 std.process.exit(1);
1051 }
1052 }
1053
1054 var exec_node = update_node.start("execute", 0);
1055 exec_node.activate();
1056 defer exec_node.end();
1057
1058 var blocks: u16 = 1000;
1059 const block_size = 1000;
1060 while (!interpreter.undefined0) {
1061 const pre_ip = interpreter.ip;
1062 if (blocks > 0) {
1063 blocks -= 1;
1064 try interpreter.ExecuteBlock(block_size);
1065 if (pre_ip == interpreter.ip) {
1066 std.debug.print("Infinite loop detected in SPU II test!\n", .{});
1067 std.process.exit(1);
1068 }
1069 }
1070 }
1071 }
1072};963};
1073964
1074fn dumpArgs(argv: []const []const u8) void {965fn dumpArgs(argv: []const []const u8) void {
src/type.zig+600-45
...@@ -69,7 +69,14 @@ pub const Type = extern union {...@@ -69,7 +69,14 @@ pub const Type = extern union {
69 .fn_ccc_void_no_args => return .Fn,69 .fn_ccc_void_no_args => return .Fn,
70 .function => return .Fn,70 .function => return .Fn,
7171
72 .array, .array_u8_sentinel_0, .array_u8, .array_sentinel => return .Array,72 .array,
73 .array_u8_sentinel_0,
74 .array_u8,
75 .array_sentinel,
76 => return .Array,
77
78 .vector => return .Vector,
79
73 .single_const_pointer_to_comptime_int,80 .single_const_pointer_to_comptime_int,
74 .const_slice_u8,81 .const_slice_u8,
75 .single_const_pointer,82 .single_const_pointer,
...@@ -83,6 +90,8 @@ pub const Type = extern union {...@@ -83,6 +90,8 @@ pub const Type = extern union {
83 .pointer,90 .pointer,
84 .inferred_alloc_const,91 .inferred_alloc_const,
85 .inferred_alloc_mut,92 .inferred_alloc_mut,
93 .manyptr_u8,
94 .manyptr_const_u8,
86 => return .Pointer,95 => return .Pointer,
8796
88 .optional,97 .optional,
...@@ -93,16 +102,30 @@ pub const Type = extern union {...@@ -93,16 +102,30 @@ pub const Type = extern union {
93102
94 .anyerror_void_error_union, .error_union => return .ErrorUnion,103 .anyerror_void_error_union, .error_union => return .ErrorUnion,
95104
105 .anyframe_T, .@"anyframe" => return .AnyFrame,
106
96 .empty_struct,107 .empty_struct,
97 .empty_struct_literal,108 .empty_struct_literal,
98 .@"struct",109 .@"struct",
110 .call_options,
111 .export_options,
112 .extern_options,
99 => return .Struct,113 => return .Struct,
100114
101 .enum_full,115 .enum_full,
102 .enum_nonexhaustive,116 .enum_nonexhaustive,
103 .enum_simple,117 .enum_simple,
118 .atomic_ordering,
119 .atomic_rmw_op,
120 .calling_convention,
121 .float_mode,
122 .reduce_op,
104 => return .Enum,123 => return .Enum,
105124
125 .@"union",
126 .union_tagged,
127 => return .Union,
128
106 .var_args_param => unreachable, // can be any type129 .var_args_param => unreachable, // can be any type
107 }130 }
108 }131 }
...@@ -205,6 +228,8 @@ pub const Type = extern union {...@@ -205,6 +228,8 @@ pub const Type = extern union {
205 .mut_slice,228 .mut_slice,
206 .optional_single_const_pointer,229 .optional_single_const_pointer,
207 .optional_single_mut_pointer,230 .optional_single_mut_pointer,
231 .manyptr_u8,
232 .manyptr_const_u8,
208 => self.cast(Payload.ElemType),233 => self.cast(Payload.ElemType),
209234
210 .inferred_alloc_const => unreachable,235 .inferred_alloc_const => unreachable,
...@@ -271,6 +296,17 @@ pub const Type = extern union {...@@ -271,6 +296,17 @@ pub const Type = extern union {
271 .@"volatile" = false,296 .@"volatile" = false,
272 .size = .Many,297 .size = .Many,
273 } },298 } },
299 .manyptr_const_u8 => return .{ .data = .{
300 .pointee_type = Type.initTag(.u8),
301 .sentinel = null,
302 .@"align" = 0,
303 .bit_offset = 0,
304 .host_size = 0,
305 .@"allowzero" = false,
306 .mutable = false,
307 .@"volatile" = false,
308 .size = .Many,
309 } },
274 .many_mut_pointer => return .{ .data = .{310 .many_mut_pointer => return .{ .data = .{
275 .pointee_type = self.castPointer().?.data,311 .pointee_type = self.castPointer().?.data,
276 .sentinel = null,312 .sentinel = null,
...@@ -282,6 +318,17 @@ pub const Type = extern union {...@@ -282,6 +318,17 @@ pub const Type = extern union {
282 .@"volatile" = false,318 .@"volatile" = false,
283 .size = .Many,319 .size = .Many,
284 } },320 } },
321 .manyptr_u8 => return .{ .data = .{
322 .pointee_type = Type.initTag(.u8),
323 .sentinel = null,
324 .@"align" = 0,
325 .bit_offset = 0,
326 .host_size = 0,
327 .@"allowzero" = false,
328 .mutable = true,
329 .@"volatile" = false,
330 .size = .Many,
331 } },
285 .c_const_pointer => return .{ .data = .{332 .c_const_pointer => return .{ .data = .{
286 .pointee_type = self.castPointer().?.data,333 .pointee_type = self.castPointer().?.data,
287 .sentinel = null,334 .sentinel = null,
...@@ -402,7 +449,7 @@ pub const Type = extern union {...@@ -402,7 +449,7 @@ pub const Type = extern union {
402 const info_b = b.intInfo(@as(Target, undefined));449 const info_b = b.intInfo(@as(Target, undefined));
403 return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits;450 return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits;
404 },451 },
405 .Array => {452 .Array, .Vector => {
406 if (a.arrayLen() != b.arrayLen())453 if (a.arrayLen() != b.arrayLen())
407 return false;454 return false;
408 if (!a.elemType().eql(b.elemType()))455 if (!a.elemType().eql(b.elemType()))
...@@ -442,16 +489,41 @@ pub const Type = extern union {...@@ -442,16 +489,41 @@ pub const Type = extern union {
442 var buf_b: Payload.ElemType = undefined;489 var buf_b: Payload.ElemType = undefined;
443 return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b));490 return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b));
444 },491 },
492 .Struct => {
493 if (a.castTag(.@"struct")) |a_payload| {
494 if (b.castTag(.@"struct")) |b_payload| {
495 return a_payload.data == b_payload.data;
496 }
497 }
498 return a.tag() == b.tag();
499 },
500 .Enum => {
501 if (a.cast(Payload.EnumFull)) |a_payload| {
502 if (b.cast(Payload.EnumFull)) |b_payload| {
503 return a_payload.data == b_payload.data;
504 }
505 }
506 if (a.cast(Payload.EnumSimple)) |a_payload| {
507 if (b.cast(Payload.EnumSimple)) |b_payload| {
508 return a_payload.data == b_payload.data;
509 }
510 }
511 return a.tag() == b.tag();
512 },
513 .Union => {
514 if (a.cast(Payload.Union)) |a_payload| {
515 if (b.cast(Payload.Union)) |b_payload| {
516 return a_payload.data == b_payload.data;
517 }
518 }
519 return a.tag() == b.tag();
520 },
521 .Opaque,
445 .Float,522 .Float,
446 .Struct,
447 .ErrorUnion,523 .ErrorUnion,
448 .ErrorSet,524 .ErrorSet,
449 .Enum,
450 .Union,
451 .BoundFn,525 .BoundFn,
452 .Opaque,
453 .Frame,526 .Frame,
454 .Vector,
455 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),527 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),
456 }528 }
457 }529 }
...@@ -486,7 +558,7 @@ pub const Type = extern union {...@@ -486,7 +558,7 @@ pub const Type = extern union {
486 std.hash.autoHash(&hasher, info.bits);558 std.hash.autoHash(&hasher, info.bits);
487 }559 }
488 },560 },
489 .Array => {561 .Array, .Vector => {
490 std.hash.autoHash(&hasher, self.arrayLen());562 std.hash.autoHash(&hasher, self.arrayLen());
491 std.hash.autoHash(&hasher, self.elemType().hash());563 std.hash.autoHash(&hasher, self.elemType().hash());
492 // TODO hash array sentinel564 // TODO hash array sentinel
...@@ -516,7 +588,6 @@ pub const Type = extern union {...@@ -516,7 +588,6 @@ pub const Type = extern union {
516 .Opaque,588 .Opaque,
517 .Frame,589 .Frame,
518 .AnyFrame,590 .AnyFrame,
519 .Vector,
520 .EnumLiteral,591 .EnumLiteral,
521 => {592 => {
522 // TODO implement more type hashing593 // TODO implement more type hashing
...@@ -576,6 +647,17 @@ pub const Type = extern union {...@@ -576,6 +647,17 @@ pub const Type = extern union {
576 .inferred_alloc_mut,647 .inferred_alloc_mut,
577 .var_args_param,648 .var_args_param,
578 .empty_struct_literal,649 .empty_struct_literal,
650 .manyptr_u8,
651 .manyptr_const_u8,
652 .atomic_ordering,
653 .atomic_rmw_op,
654 .calling_convention,
655 .float_mode,
656 .reduce_op,
657 .call_options,
658 .export_options,
659 .extern_options,
660 .@"anyframe",
579 => unreachable,661 => unreachable,
580662
581 .array_u8,663 .array_u8,
...@@ -593,12 +675,20 @@ pub const Type = extern union {...@@ -593,12 +675,20 @@ pub const Type = extern union {
593 .optional,675 .optional,
594 .optional_single_mut_pointer,676 .optional_single_mut_pointer,
595 .optional_single_const_pointer,677 .optional_single_const_pointer,
678 .anyframe_T,
596 => return self.copyPayloadShallow(allocator, Payload.ElemType),679 => return self.copyPayloadShallow(allocator, Payload.ElemType),
597680
598 .int_signed,681 .int_signed,
599 .int_unsigned,682 .int_unsigned,
600 => return self.copyPayloadShallow(allocator, Payload.Bits),683 => return self.copyPayloadShallow(allocator, Payload.Bits),
601684
685 .vector => {
686 const payload = self.castTag(.vector).?.data;
687 return Tag.vector.create(allocator, .{
688 .len = payload.len,
689 .elem_type = try payload.elem_type.copy(allocator),
690 });
691 },
602 .array => {692 .array => {
603 const payload = self.castTag(.array).?.data;693 const payload = self.castTag(.array).?.data;
604 return Tag.array.create(allocator, .{694 return Tag.array.create(allocator, .{
...@@ -656,6 +746,7 @@ pub const Type = extern union {...@@ -656,6 +746,7 @@ pub const Type = extern union {
656 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),746 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),
657 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),747 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),
658 .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct),748 .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct),
749 .@"union", .union_tagged => return self.copyPayloadShallow(allocator, Payload.Union),
659 .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple),750 .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple),
660 .enum_full, .enum_nonexhaustive => return self.copyPayloadShallow(allocator, Payload.EnumFull),751 .enum_full, .enum_nonexhaustive => return self.copyPayloadShallow(allocator, Payload.EnumFull),
661 .@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque),752 .@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque),
...@@ -710,6 +801,7 @@ pub const Type = extern union {...@@ -710,6 +801,7 @@ pub const Type = extern union {
710 .void,801 .void,
711 .type,802 .type,
712 .anyerror,803 .anyerror,
804 .@"anyframe",
713 .comptime_int,805 .comptime_int,
714 .comptime_float,806 .comptime_float,
715 .noreturn,807 .noreturn,
...@@ -726,6 +818,10 @@ pub const Type = extern union {...@@ -726,6 +818,10 @@ pub const Type = extern union {
726 const struct_obj = ty.castTag(.@"struct").?.data;818 const struct_obj = ty.castTag(.@"struct").?.data;
727 return struct_obj.owner_decl.renderFullyQualifiedName(writer);819 return struct_obj.owner_decl.renderFullyQualifiedName(writer);
728 },820 },
821 .@"union", .union_tagged => {
822 const union_obj = ty.cast(Payload.Union).?.data;
823 return union_obj.owner_decl.renderFullyQualifiedName(writer);
824 },
729 .enum_full, .enum_nonexhaustive => {825 .enum_full, .enum_nonexhaustive => {
730 const enum_full = ty.cast(Payload.EnumFull).?.data;826 const enum_full = ty.cast(Payload.EnumFull).?.data;
731 return enum_full.owner_decl.renderFullyQualifiedName(writer);827 return enum_full.owner_decl.renderFullyQualifiedName(writer);
...@@ -746,6 +842,16 @@ pub const Type = extern union {...@@ -746,6 +842,16 @@ pub const Type = extern union {
746 .fn_naked_noreturn_no_args => return writer.writeAll("fn() callconv(.Naked) noreturn"),842 .fn_naked_noreturn_no_args => return writer.writeAll("fn() callconv(.Naked) noreturn"),
747 .fn_ccc_void_no_args => return writer.writeAll("fn() callconv(.C) void"),843 .fn_ccc_void_no_args => return writer.writeAll("fn() callconv(.C) void"),
748 .single_const_pointer_to_comptime_int => return writer.writeAll("*const comptime_int"),844 .single_const_pointer_to_comptime_int => return writer.writeAll("*const comptime_int"),
845 .manyptr_u8 => return writer.writeAll("[*]u8"),
846 .manyptr_const_u8 => return writer.writeAll("[*]const u8"),
847 .atomic_ordering => return writer.writeAll("std.builtin.AtomicOrdering"),
848 .atomic_rmw_op => return writer.writeAll("std.builtin.AtomicRmwOp"),
849 .calling_convention => return writer.writeAll("std.builtin.CallingConvention"),
850 .float_mode => return writer.writeAll("std.builtin.FloatMode"),
851 .reduce_op => return writer.writeAll("std.builtin.ReduceOp"),
852 .call_options => return writer.writeAll("std.builtin.CallOptions"),
853 .export_options => return writer.writeAll("std.builtin.ExportOptions"),
854 .extern_options => return writer.writeAll("std.builtin.ExternOptions"),
749 .function => {855 .function => {
750 const payload = ty.castTag(.function).?.data;856 const payload = ty.castTag(.function).?.data;
751 try writer.writeAll("fn(");857 try writer.writeAll("fn(");
...@@ -766,6 +872,12 @@ pub const Type = extern union {...@@ -766,6 +872,12 @@ pub const Type = extern union {
766 continue;872 continue;
767 },873 },
768874
875 .anyframe_T => {
876 const return_type = ty.castTag(.anyframe_T).?.data;
877 try writer.print("anyframe->", .{});
878 ty = return_type;
879 continue;
880 },
769 .array_u8 => {881 .array_u8 => {
770 const len = ty.castTag(.array_u8).?.data;882 const len = ty.castTag(.array_u8).?.data;
771 return writer.print("[{d}]u8", .{len});883 return writer.print("[{d}]u8", .{len});
...@@ -774,6 +886,12 @@ pub const Type = extern union {...@@ -774,6 +886,12 @@ pub const Type = extern union {
774 const len = ty.castTag(.array_u8_sentinel_0).?.data;886 const len = ty.castTag(.array_u8_sentinel_0).?.data;
775 return writer.print("[{d}:0]u8", .{len});887 return writer.print("[{d}:0]u8", .{len});
776 },888 },
889 .vector => {
890 const payload = ty.castTag(.vector).?.data;
891 try writer.print("@Vector({d}, ", .{payload.len});
892 try payload.elem_type.format("", .{}, writer);
893 return writer.writeAll(")");
894 },
777 .array => {895 .array => {
778 const payload = ty.castTag(.array).?.data;896 const payload = ty.castTag(.array).?.data;
779 try writer.print("[{d}]", .{payload.len});897 try writer.print("[{d}]", .{payload.len});
...@@ -940,6 +1058,7 @@ pub const Type = extern union {...@@ -940,6 +1058,7 @@ pub const Type = extern union {
940 .void => return Value.initTag(.void_type),1058 .void => return Value.initTag(.void_type),
941 .type => return Value.initTag(.type_type),1059 .type => return Value.initTag(.type_type),
942 .anyerror => return Value.initTag(.anyerror_type),1060 .anyerror => return Value.initTag(.anyerror_type),
1061 .@"anyframe" => return Value.initTag(.anyframe_type),
943 .comptime_int => return Value.initTag(.comptime_int_type),1062 .comptime_int => return Value.initTag(.comptime_int_type),
944 .comptime_float => return Value.initTag(.comptime_float_type),1063 .comptime_float => return Value.initTag(.comptime_float_type),
945 .noreturn => return Value.initTag(.noreturn_type),1064 .noreturn => return Value.initTag(.noreturn_type),
...@@ -952,6 +1071,16 @@ pub const Type = extern union {...@@ -952,6 +1071,16 @@ pub const Type = extern union {
952 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),1071 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
953 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),1072 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),
954 .enum_literal => return Value.initTag(.enum_literal_type),1073 .enum_literal => return Value.initTag(.enum_literal_type),
1074 .manyptr_u8 => return Value.initTag(.manyptr_u8_type),
1075 .manyptr_const_u8 => return Value.initTag(.manyptr_const_u8_type),
1076 .atomic_ordering => return Value.initTag(.atomic_ordering_type),
1077 .atomic_rmw_op => return Value.initTag(.atomic_rmw_op_type),
1078 .calling_convention => return Value.initTag(.calling_convention_type),
1079 .float_mode => return Value.initTag(.float_mode_type),
1080 .reduce_op => return Value.initTag(.reduce_op_type),
1081 .call_options => return Value.initTag(.call_options_type),
1082 .export_options => return Value.initTag(.export_options_type),
1083 .extern_options => return Value.initTag(.extern_options_type),
955 .inferred_alloc_const => unreachable,1084 .inferred_alloc_const => unreachable,
956 .inferred_alloc_mut => unreachable,1085 .inferred_alloc_mut => unreachable,
957 else => return Value.Tag.ty.create(allocator, self),1086 else => return Value.Tag.ty.create(allocator, self),
...@@ -1001,6 +1130,18 @@ pub const Type = extern union {...@@ -1001,6 +1130,18 @@ pub const Type = extern union {
1001 .anyerror_void_error_union,1130 .anyerror_void_error_union,
1002 .error_set,1131 .error_set,
1003 .error_set_single,1132 .error_set_single,
1133 .manyptr_u8,
1134 .manyptr_const_u8,
1135 .atomic_ordering,
1136 .atomic_rmw_op,
1137 .calling_convention,
1138 .float_mode,
1139 .reduce_op,
1140 .call_options,
1141 .export_options,
1142 .extern_options,
1143 .@"anyframe",
1144 .anyframe_T,
1004 => true,1145 => true,
10051146
1006 .@"struct" => {1147 .@"struct" => {
...@@ -1026,9 +1167,30 @@ pub const Type = extern union {...@@ -1026,9 +1167,30 @@ pub const Type = extern union {
1026 const int_tag_ty = self.intTagType(&buffer);1167 const int_tag_ty = self.intTagType(&buffer);
1027 return int_tag_ty.hasCodeGenBits();1168 return int_tag_ty.hasCodeGenBits();
1028 },1169 },
1170 .@"union" => {
1171 const union_obj = self.castTag(.@"union").?.data;
1172 for (union_obj.fields.entries.items) |entry| {
1173 if (entry.value.ty.hasCodeGenBits())
1174 return true;
1175 } else {
1176 return false;
1177 }
1178 },
1179 .union_tagged => {
1180 const union_obj = self.castTag(.@"union").?.data;
1181 if (union_obj.tag_ty.hasCodeGenBits()) {
1182 return true;
1183 }
1184 for (union_obj.fields.entries.items) |entry| {
1185 if (entry.value.ty.hasCodeGenBits())
1186 return true;
1187 } else {
1188 return false;
1189 }
1190 },
10291191
1030 // TODO lazy types1192 // TODO lazy types
1031 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,1193 .array, .vector => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
1032 .array_u8 => self.arrayLen() != 0,1194 .array_u8 => self.arrayLen() != 0,
1033 .array_sentinel, .single_const_pointer, .single_mut_pointer, .many_const_pointer, .many_mut_pointer, .c_const_pointer, .c_mut_pointer, .const_slice, .mut_slice, .pointer => self.elemType().hasCodeGenBits(),1195 .array_sentinel, .single_const_pointer, .single_mut_pointer, .many_const_pointer, .many_mut_pointer, .c_const_pointer, .c_mut_pointer, .const_slice, .mut_slice, .pointer => self.elemType().hasCodeGenBits(),
1034 .int_signed, .int_unsigned => self.cast(Payload.Bits).?.data != 0,1196 .int_signed, .int_unsigned => self.cast(Payload.Bits).?.data != 0,
...@@ -1079,14 +1241,17 @@ pub const Type = extern union {...@@ -1079,14 +1241,17 @@ pub const Type = extern union {
1079 .optional_single_mut_pointer,1241 .optional_single_mut_pointer,
1080 => return self.cast(Payload.ElemType).?.data.abiAlignment(target),1242 => return self.cast(Payload.ElemType).?.data.abiAlignment(target),
10811243
1082 .const_slice_u8 => return 1,1244 .manyptr_u8,
1245 .manyptr_const_u8,
1246 .const_slice_u8,
1247 => return 1,
10831248
1084 .pointer => {1249 .pointer => {
1085 const ptr_info = self.castTag(.pointer).?.data;1250 const ptr_info = self.castTag(.pointer).?.data;
1086 if (ptr_info.@"align" != 0) {1251 if (ptr_info.@"align" != 0) {
1087 return ptr_info.@"align";1252 return ptr_info.@"align";
1088 } else {1253 } else {
1089 return ptr_info.pointee_type.abiAlignment();1254 return ptr_info.pointee_type.abiAlignment(target);
1090 }1255 }
1091 },1256 },
10921257
...@@ -1102,6 +1267,14 @@ pub const Type = extern union {...@@ -1102,6 +1267,14 @@ pub const Type = extern union {
1102 .bool,1267 .bool,
1103 .array_u8_sentinel_0,1268 .array_u8_sentinel_0,
1104 .array_u8,1269 .array_u8,
1270 .atomic_ordering,
1271 .atomic_rmw_op,
1272 .calling_convention,
1273 .float_mode,
1274 .reduce_op,
1275 .call_options,
1276 .export_options,
1277 .extern_options,
1105 => return 1,1278 => return 1,
11061279
1107 .fn_noreturn_no_args, // represents machine code; not a pointer1280 .fn_noreturn_no_args, // represents machine code; not a pointer
...@@ -1136,6 +1309,10 @@ pub const Type = extern union {...@@ -1136,6 +1309,10 @@ pub const Type = extern union {
1136 .optional_single_const_pointer,1309 .optional_single_const_pointer,
1137 .optional_single_mut_pointer,1310 .optional_single_mut_pointer,
1138 .pointer,1311 .pointer,
1312 .manyptr_u8,
1313 .manyptr_const_u8,
1314 .@"anyframe",
1315 .anyframe_T,
1139 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),1316 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
11401317
1141 .c_short => return @divExact(CType.short.sizeInBits(target), 8),1318 .c_short => return @divExact(CType.short.sizeInBits(target), 8),
...@@ -1161,6 +1338,10 @@ pub const Type = extern union {...@@ -1161,6 +1338,10 @@ pub const Type = extern union {
11611338
1162 .array, .array_sentinel => return self.elemType().abiAlignment(target),1339 .array, .array_sentinel => return self.elemType().abiAlignment(target),
11631340
1341 // TODO audit this - is there any more complicated logic to determine
1342 // ABI alignment of vectors?
1343 .vector => return 16,
1344
1164 .int_signed, .int_unsigned => {1345 .int_signed, .int_unsigned => {
1165 const bits: u16 = self.cast(Payload.Bits).?.data;1346 const bits: u16 = self.cast(Payload.Bits).?.data;
1166 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);1347 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);
...@@ -1215,6 +1396,34 @@ pub const Type = extern union {...@@ -1215,6 +1396,34 @@ pub const Type = extern union {
1215 const int_tag_ty = self.intTagType(&buffer);1396 const int_tag_ty = self.intTagType(&buffer);
1216 return int_tag_ty.abiAlignment(target);1397 return int_tag_ty.abiAlignment(target);
1217 },1398 },
1399 .union_tagged => {
1400 const union_obj = self.castTag(.union_tagged).?.data;
1401 var biggest: u32 = union_obj.tag_ty.abiAlignment(target);
1402 for (union_obj.fields.entries.items) |entry| {
1403 const field_ty = entry.value.ty;
1404 if (!field_ty.hasCodeGenBits()) continue;
1405 const field_align = field_ty.abiAlignment(target);
1406 if (field_align > biggest) {
1407 biggest = field_align;
1408 }
1409 }
1410 assert(biggest != 0);
1411 return biggest;
1412 },
1413 .@"union" => {
1414 const union_obj = self.castTag(.@"union").?.data;
1415 var biggest: u32 = 0;
1416 for (union_obj.fields.entries.items) |entry| {
1417 const field_ty = entry.value.ty;
1418 if (!field_ty.hasCodeGenBits()) continue;
1419 const field_align = field_ty.abiAlignment(target);
1420 if (field_align > biggest) {
1421 biggest = field_align;
1422 }
1423 }
1424 assert(biggest != 0);
1425 return biggest;
1426 },
1218 .c_void,1427 .c_void,
1219 .void,1428 .void,
1220 .type,1429 .type,
...@@ -1267,16 +1476,27 @@ pub const Type = extern union {...@@ -1267,16 +1476,27 @@ pub const Type = extern union {
1267 const int_tag_ty = self.intTagType(&buffer);1476 const int_tag_ty = self.intTagType(&buffer);
1268 return int_tag_ty.abiSize(target);1477 return int_tag_ty.abiSize(target);
1269 },1478 },
1479 .@"union", .union_tagged => {
1480 @panic("TODO abiSize unions");
1481 },
12701482
1271 .u8,1483 .u8,
1272 .i8,1484 .i8,
1273 .bool,1485 .bool,
1486 .atomic_ordering,
1487 .atomic_rmw_op,
1488 .calling_convention,
1489 .float_mode,
1490 .reduce_op,
1491 .call_options,
1492 .export_options,
1493 .extern_options,
1274 => return 1,1494 => return 1,
12751495
1276 .array_u8 => self.castTag(.array_u8).?.data,1496 .array_u8 => self.castTag(.array_u8).?.data,
1277 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1,1497 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1,
1278 .array => {1498 .array, .vector => {
1279 const payload = self.castTag(.array).?.data;1499 const payload = self.cast(Payload.Array).?.data;
1280 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));1500 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
1281 return payload.len * elem_size;1501 return payload.len * elem_size;
1282 },1502 },
...@@ -1293,7 +1513,11 @@ pub const Type = extern union {...@@ -1293,7 +1513,11 @@ pub const Type = extern union {
1293 .i64, .u64 => return 8,1513 .i64, .u64 => return 8,
1294 .u128, .i128 => return 16,1514 .u128, .i128 => return 16,
12951515
1296 .isize, .usize => return @divExact(target.cpu.arch.ptrBitWidth(), 8),1516 .isize,
1517 .usize,
1518 .@"anyframe",
1519 .anyframe_T,
1520 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
12971521
1298 .const_slice,1522 .const_slice,
1299 .mut_slice,1523 .mut_slice,
...@@ -1322,6 +1546,10 @@ pub const Type = extern union {...@@ -1322,6 +1546,10 @@ pub const Type = extern union {
1322 return @divExact(target.cpu.arch.ptrBitWidth(), 8);1546 return @divExact(target.cpu.arch.ptrBitWidth(), 8);
1323 },1547 },
13241548
1549 .manyptr_u8,
1550 .manyptr_const_u8,
1551 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
1552
1325 .c_short => return @divExact(CType.short.sizeInBits(target), 8),1553 .c_short => return @divExact(CType.short.sizeInBits(target), 8),
1326 .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8),1554 .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8),
1327 .c_int => return @divExact(CType.int.sizeInBits(target), 8),1555 .c_int => return @divExact(CType.int.sizeInBits(target), 8),
...@@ -1377,6 +1605,177 @@ pub const Type = extern union {...@@ -1377,6 +1605,177 @@ pub const Type = extern union {
1377 };1605 };
1378 }1606 }
13791607
1608 /// Asserts the type has the bit size already resolved.
1609 pub fn bitSize(self: Type, target: Target) u64 {
1610 return switch (self.tag()) {
1611 .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer
1612 .fn_void_no_args => unreachable, // represents machine code; not a pointer
1613 .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer
1614 .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer
1615 .function => unreachable, // represents machine code; not a pointer
1616 .c_void => unreachable,
1617 .void => unreachable,
1618 .type => unreachable,
1619 .comptime_int => unreachable,
1620 .comptime_float => unreachable,
1621 .noreturn => unreachable,
1622 .@"null" => unreachable,
1623 .@"undefined" => unreachable,
1624 .enum_literal => unreachable,
1625 .single_const_pointer_to_comptime_int => unreachable,
1626 .empty_struct => unreachable,
1627 .empty_struct_literal => unreachable,
1628 .inferred_alloc_const => unreachable,
1629 .inferred_alloc_mut => unreachable,
1630 .@"opaque" => unreachable,
1631 .var_args_param => unreachable,
1632
1633 .@"struct" => {
1634 @panic("TODO bitSize struct");
1635 },
1636 .enum_simple, .enum_full, .enum_nonexhaustive => {
1637 var buffer: Payload.Bits = undefined;
1638 const int_tag_ty = self.intTagType(&buffer);
1639 return int_tag_ty.bitSize(target);
1640 },
1641 .@"union", .union_tagged => {
1642 @panic("TODO bitSize unions");
1643 },
1644
1645 .u8, .i8 => 8,
1646
1647 .bool => 1,
1648
1649 .vector => {
1650 const payload = self.castTag(.vector).?.data;
1651 const elem_bit_size = payload.elem_type.bitSize(target);
1652 return elem_bit_size * payload.len;
1653 },
1654 .array_u8 => 8 * self.castTag(.array_u8).?.data,
1655 .array_u8_sentinel_0 => 8 * (self.castTag(.array_u8_sentinel_0).?.data + 1),
1656 .array => {
1657 const payload = self.castTag(.array).?.data;
1658 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
1659 if (elem_size == 0 or payload.len == 0)
1660 return 0;
1661 return (payload.len - 1) * 8 * elem_size + payload.elem_type.bitSize(target);
1662 },
1663 .array_sentinel => {
1664 const payload = self.castTag(.array_sentinel).?.data;
1665 const elem_size = std.math.max(
1666 payload.elem_type.abiAlignment(target),
1667 payload.elem_type.abiSize(target),
1668 );
1669 return payload.len * 8 * elem_size + payload.elem_type.bitSize(target);
1670 },
1671 .i16, .u16, .f16 => 16,
1672 .i32, .u32, .f32 => 32,
1673 .i64, .u64, .f64 => 64,
1674 .u128, .i128, .f128 => 128,
1675
1676 .isize,
1677 .usize,
1678 .@"anyframe",
1679 .anyframe_T,
1680 => target.cpu.arch.ptrBitWidth(),
1681
1682 .const_slice,
1683 .mut_slice,
1684 => {
1685 if (self.elemType().hasCodeGenBits()) {
1686 return target.cpu.arch.ptrBitWidth() * 2;
1687 } else {
1688 return target.cpu.arch.ptrBitWidth();
1689 }
1690 },
1691 .const_slice_u8 => target.cpu.arch.ptrBitWidth() * 2,
1692
1693 .optional_single_const_pointer,
1694 .optional_single_mut_pointer,
1695 => {
1696 if (self.elemType().hasCodeGenBits()) {
1697 return target.cpu.arch.ptrBitWidth();
1698 } else {
1699 return 1;
1700 }
1701 },
1702
1703 .single_const_pointer,
1704 .single_mut_pointer,
1705 .many_const_pointer,
1706 .many_mut_pointer,
1707 .c_const_pointer,
1708 .c_mut_pointer,
1709 .pointer,
1710 => {
1711 if (self.elemType().hasCodeGenBits()) {
1712 return target.cpu.arch.ptrBitWidth();
1713 } else {
1714 return 0;
1715 }
1716 },
1717
1718 .manyptr_u8,
1719 .manyptr_const_u8,
1720 => return target.cpu.arch.ptrBitWidth(),
1721
1722 .c_short => return CType.short.sizeInBits(target),
1723 .c_ushort => return CType.ushort.sizeInBits(target),
1724 .c_int => return CType.int.sizeInBits(target),
1725 .c_uint => return CType.uint.sizeInBits(target),
1726 .c_long => return CType.long.sizeInBits(target),
1727 .c_ulong => return CType.ulong.sizeInBits(target),
1728 .c_longlong => return CType.longlong.sizeInBits(target),
1729 .c_ulonglong => return CType.ulonglong.sizeInBits(target),
1730 .c_longdouble => 128,
1731
1732 .error_set,
1733 .error_set_single,
1734 .anyerror_void_error_union,
1735 .anyerror,
1736 => return 16, // TODO revisit this when we have the concept of the error tag type
1737
1738 .int_signed, .int_unsigned => self.cast(Payload.Bits).?.data,
1739
1740 .optional => {
1741 var buf: Payload.ElemType = undefined;
1742 const child_type = self.optionalChild(&buf);
1743 if (!child_type.hasCodeGenBits()) return 8;
1744
1745 if (child_type.zigTypeTag() == .Pointer and !child_type.isCPtr())
1746 return target.cpu.arch.ptrBitWidth();
1747
1748 // Optional types are represented as a struct with the child type as the first
1749 // field and a boolean as the second. Since the child type's abi alignment is
1750 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
1751 // to the child type's ABI alignment.
1752 return child_type.bitSize(target) + 1;
1753 },
1754
1755 .error_union => {
1756 const payload = self.castTag(.error_union).?.data;
1757 if (!payload.error_set.hasCodeGenBits() and !payload.payload.hasCodeGenBits()) {
1758 return 0;
1759 } else if (!payload.error_set.hasCodeGenBits()) {
1760 return payload.payload.bitSize(target);
1761 } else if (!payload.payload.hasCodeGenBits()) {
1762 return payload.error_set.bitSize(target);
1763 }
1764 @panic("TODO bitSize error union");
1765 },
1766
1767 .atomic_ordering,
1768 .atomic_rmw_op,
1769 .calling_convention,
1770 .float_mode,
1771 .reduce_op,
1772 .call_options,
1773 .export_options,
1774 .extern_options,
1775 => @panic("TODO at some point we gotta resolve builtin types"),
1776 };
1777 }
1778
1380 /// Asserts the type is an enum.1779 /// Asserts the type is an enum.
1381 pub fn intTagType(self: Type, buffer: *Payload.Bits) Type {1780 pub fn intTagType(self: Type, buffer: *Payload.Bits) Type {
1382 switch (self.tag()) {1781 switch (self.tag()) {
...@@ -1419,6 +1818,8 @@ pub const Type = extern union {...@@ -1419,6 +1818,8 @@ pub const Type = extern union {
14191818
1420 .many_const_pointer,1819 .many_const_pointer,
1421 .many_mut_pointer,1820 .many_mut_pointer,
1821 .manyptr_u8,
1822 .manyptr_const_u8,
1422 => .Many,1823 => .Many,
14231824
1424 .c_const_pointer,1825 .c_const_pointer,
...@@ -1459,6 +1860,7 @@ pub const Type = extern union {...@@ -1459,6 +1860,7 @@ pub const Type = extern union {
1459 .single_const_pointer_to_comptime_int,1860 .single_const_pointer_to_comptime_int,
1460 .const_slice_u8,1861 .const_slice_u8,
1461 .const_slice,1862 .const_slice,
1863 .manyptr_const_u8,
1462 => true,1864 => true,
14631865
1464 .pointer => !self.castTag(.pointer).?.data.mutable,1866 .pointer => !self.castTag(.pointer).?.data.mutable,
...@@ -1526,7 +1928,6 @@ pub const Type = extern union {...@@ -1526,7 +1928,6 @@ pub const Type = extern union {
1526 .Enum,1928 .Enum,
1527 .Frame,1929 .Frame,
1528 .AnyFrame,1930 .AnyFrame,
1529 .Vector,
1530 => return true,1931 => return true,
15311932
1532 .Opaque => return is_extern,1933 .Opaque => return is_extern,
...@@ -1545,7 +1946,7 @@ pub const Type = extern union {...@@ -1545,7 +1946,7 @@ pub const Type = extern union {
1545 var buf: Payload.ElemType = undefined;1946 var buf: Payload.ElemType = undefined;
1546 return ty.optionalChild(&buf).isValidVarType(is_extern);1947 return ty.optionalChild(&buf).isValidVarType(is_extern);
1547 },1948 },
1548 .Pointer, .Array => ty = ty.elemType(),1949 .Pointer, .Array, .Vector => ty = ty.elemType(),
1549 .ErrorUnion => ty = ty.errorUnionChild(),1950 .ErrorUnion => ty = ty.errorUnionChild(),
15501951
1551 .Fn => @panic("TODO fn isValidVarType"),1952 .Fn => @panic("TODO fn isValidVarType"),
...@@ -1561,6 +1962,7 @@ pub const Type = extern union {...@@ -1561,6 +1962,7 @@ pub const Type = extern union {
1561 /// Asserts the type is a pointer or array type.1962 /// Asserts the type is a pointer or array type.
1562 pub fn elemType(self: Type) Type {1963 pub fn elemType(self: Type) Type {
1563 return switch (self.tag()) {1964 return switch (self.tag()) {
1965 .vector => self.castTag(.vector).?.data.elem_type,
1564 .array => self.castTag(.array).?.data.elem_type,1966 .array => self.castTag(.array).?.data.elem_type,
1565 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,1967 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,
1566 .single_const_pointer,1968 .single_const_pointer,
...@@ -1573,7 +1975,13 @@ pub const Type = extern union {...@@ -1573,7 +1975,13 @@ pub const Type = extern union {
1573 .mut_slice,1975 .mut_slice,
1574 => self.castPointer().?.data,1976 => self.castPointer().?.data,
15751977
1576 .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),1978 .array_u8,
1979 .array_u8_sentinel_0,
1980 .const_slice_u8,
1981 .manyptr_u8,
1982 .manyptr_const_u8,
1983 => Type.initTag(.u8),
1984
1577 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),1985 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
1578 .pointer => self.castTag(.pointer).?.data.pointee_type,1986 .pointer => self.castTag(.pointer).?.data.pointee_type,
15791987
...@@ -1645,6 +2053,7 @@ pub const Type = extern union {...@@ -1645,6 +2053,7 @@ pub const Type = extern union {
1645 /// Asserts the type is an array or vector.2053 /// Asserts the type is an array or vector.
1646 pub fn arrayLen(self: Type) u64 {2054 pub fn arrayLen(self: Type) u64 {
1647 return switch (self.tag()) {2055 return switch (self.tag()) {
2056 .vector => self.castTag(.vector).?.data.len,
1648 .array => self.castTag(.array).?.data.len,2057 .array => self.castTag(.array).?.data.len,
1649 .array_sentinel => self.castTag(.array_sentinel).?.data.len,2058 .array_sentinel => self.castTag(.array_sentinel).?.data.len,
1650 .array_u8 => self.castTag(.array_u8).?.data,2059 .array_u8 => self.castTag(.array_u8).?.data,
...@@ -1664,8 +2073,11 @@ pub const Type = extern union {...@@ -1664,8 +2073,11 @@ pub const Type = extern union {
1664 .c_const_pointer,2073 .c_const_pointer,
1665 .c_mut_pointer,2074 .c_mut_pointer,
1666 .single_const_pointer_to_comptime_int,2075 .single_const_pointer_to_comptime_int,
2076 .vector,
1667 .array,2077 .array,
1668 .array_u8,2078 .array_u8,
2079 .manyptr_u8,
2080 .manyptr_const_u8,
1669 => return null,2081 => return null,
16702082
1671 .pointer => return self.castTag(.pointer).?.data.sentinel,2083 .pointer => return self.castTag(.pointer).?.data.sentinel,
...@@ -1922,6 +2334,8 @@ pub const Type = extern union {...@@ -1922,6 +2334,8 @@ pub const Type = extern union {
1922 };2334 };
1923 }2335 }
19242336
2337 /// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which
2338 /// resolves field types rather than asserting they are already resolved.
1925 pub fn onePossibleValue(starting_type: Type) ?Value {2339 pub fn onePossibleValue(starting_type: Type) ?Value {
1926 var ty = starting_type;2340 var ty = starting_type;
1927 while (true) switch (ty.tag()) {2341 while (true) switch (ty.tag()) {
...@@ -1977,10 +2391,30 @@ pub const Type = extern union {...@@ -1977,10 +2391,30 @@ pub const Type = extern union {
1977 .error_set_single,2391 .error_set_single,
1978 .@"opaque",2392 .@"opaque",
1979 .var_args_param,2393 .var_args_param,
2394 .manyptr_u8,
2395 .manyptr_const_u8,
2396 .atomic_ordering,
2397 .atomic_rmw_op,
2398 .calling_convention,
2399 .float_mode,
2400 .reduce_op,
2401 .call_options,
2402 .export_options,
2403 .extern_options,
2404 .@"anyframe",
2405 .anyframe_T,
2406 .many_const_pointer,
2407 .many_mut_pointer,
2408 .c_const_pointer,
2409 .c_mut_pointer,
2410 .single_const_pointer,
2411 .single_mut_pointer,
2412 .pointer,
1980 => return null,2413 => return null,
19812414
1982 .@"struct" => {2415 .@"struct" => {
1983 const s = ty.castTag(.@"struct").?.data;2416 const s = ty.castTag(.@"struct").?.data;
2417 assert(s.haveFieldTypes());
1984 for (s.fields.entries.items) |entry| {2418 for (s.fields.entries.items) |entry| {
1985 const field_ty = entry.value.ty;2419 const field_ty = entry.value.ty;
1986 if (field_ty.onePossibleValue() == null) {2420 if (field_ty.onePossibleValue() == null) {
...@@ -2006,6 +2440,12 @@ pub const Type = extern union {...@@ -2006,6 +2440,12 @@ pub const Type = extern union {
2006 }2440 }
2007 },2441 },
2008 .enum_nonexhaustive => ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty,2442 .enum_nonexhaustive => ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty,
2443 .@"union" => {
2444 return null; // TODO
2445 },
2446 .union_tagged => {
2447 return null; // TODO
2448 },
20092449
2010 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),2450 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
2011 .void => return Value.initTag(.void_value),2451 .void => return Value.initTag(.void_value),
...@@ -2020,26 +2460,13 @@ pub const Type = extern union {...@@ -2020,26 +2460,13 @@ pub const Type = extern union {
2020 return null;2460 return null;
2021 }2461 }
2022 },2462 },
2023 .array, .array_u8 => {2463 .vector, .array, .array_u8 => {
2024 if (ty.arrayLen() == 0)2464 if (ty.arrayLen() == 0)
2025 return Value.initTag(.empty_array);2465 return Value.initTag(.empty_array);
2026 ty = ty.elemType();2466 ty = ty.elemType();
2027 continue;2467 continue;
2028 },2468 },
2029 .many_const_pointer,2469
2030 .many_mut_pointer,
2031 .c_const_pointer,
2032 .c_mut_pointer,
2033 .single_const_pointer,
2034 .single_mut_pointer,
2035 => {
2036 ty = ty.castPointer().?.data;
2037 continue;
2038 },
2039 .pointer => {
2040 ty = ty.castTag(.pointer).?.data.pointee_type;
2041 continue;
2042 },
2043 .inferred_alloc_const => unreachable,2470 .inferred_alloc_const => unreachable,
2044 .inferred_alloc_mut => unreachable,2471 .inferred_alloc_mut => unreachable,
2045 };2472 };
...@@ -2052,13 +2479,15 @@ pub const Type = extern union {...@@ -2052,13 +2479,15 @@ pub const Type = extern union {
2052 (self.isSinglePointer() and self.elemType().zigTypeTag() == .Array);2479 (self.isSinglePointer() and self.elemType().zigTypeTag() == .Array);
2053 }2480 }
20542481
2055 /// Returns null if the type has no container.2482 /// Returns null if the type has no namespace.
2056 pub fn getContainerScope(self: Type) ?*Module.Scope.Container {2483 pub fn getNamespace(self: Type) ?*Module.Scope.Namespace {
2057 return switch (self.tag()) {2484 return switch (self.tag()) {
2058 .@"struct" => &self.castTag(.@"struct").?.data.container,2485 .@"struct" => &self.castTag(.@"struct").?.data.namespace,
2059 .enum_full => &self.castTag(.enum_full).?.data.container,2486 .enum_full => &self.castTag(.enum_full).?.data.namespace,
2060 .empty_struct => self.castTag(.empty_struct).?.data,2487 .empty_struct => self.castTag(.empty_struct).?.data,
2061 .@"opaque" => &self.castTag(.@"opaque").?.data,2488 .@"opaque" => &self.castTag(.@"opaque").?.data,
2489 .@"union" => &self.castTag(.@"union").?.data.namespace,
2490 .union_tagged => &self.castTag(.union_tagged).?.data.namespace,
20622491
2063 else => null,2492 else => null,
2064 };2493 };
...@@ -2136,6 +2565,16 @@ pub const Type = extern union {...@@ -2136,6 +2565,16 @@ pub const Type = extern union {
2136 const enum_simple = ty.castTag(.enum_simple).?.data;2565 const enum_simple = ty.castTag(.enum_simple).?.data;
2137 return enum_simple.fields.count();2566 return enum_simple.fields.count();
2138 },2567 },
2568 .atomic_ordering,
2569 .atomic_rmw_op,
2570 .calling_convention,
2571 .float_mode,
2572 .reduce_op,
2573 .call_options,
2574 .export_options,
2575 .extern_options,
2576 => @panic("TODO resolve std.builtin types"),
2577
2139 else => unreachable,2578 else => unreachable,
2140 }2579 }
2141 }2580 }
...@@ -2150,6 +2589,15 @@ pub const Type = extern union {...@@ -2150,6 +2589,15 @@ pub const Type = extern union {
2150 const enum_simple = ty.castTag(.enum_simple).?.data;2589 const enum_simple = ty.castTag(.enum_simple).?.data;
2151 return enum_simple.fields.entries.items[field_index].key;2590 return enum_simple.fields.entries.items[field_index].key;
2152 },2591 },
2592 .atomic_ordering,
2593 .atomic_rmw_op,
2594 .calling_convention,
2595 .float_mode,
2596 .reduce_op,
2597 .call_options,
2598 .export_options,
2599 .extern_options,
2600 => @panic("TODO resolve std.builtin types"),
2153 else => unreachable,2601 else => unreachable,
2154 }2602 }
2155 }2603 }
...@@ -2164,6 +2612,15 @@ pub const Type = extern union {...@@ -2164,6 +2612,15 @@ pub const Type = extern union {
2164 const enum_simple = ty.castTag(.enum_simple).?.data;2612 const enum_simple = ty.castTag(.enum_simple).?.data;
2165 return enum_simple.fields.getIndex(field_name);2613 return enum_simple.fields.getIndex(field_name);
2166 },2614 },
2615 .atomic_ordering,
2616 .atomic_rmw_op,
2617 .calling_convention,
2618 .float_mode,
2619 .reduce_op,
2620 .call_options,
2621 .export_options,
2622 .extern_options,
2623 => @panic("TODO resolve std.builtin types"),
2167 else => unreachable,2624 else => unreachable,
2168 }2625 }
2169 }2626 }
...@@ -2200,6 +2657,15 @@ pub const Type = extern union {...@@ -2200,6 +2657,15 @@ pub const Type = extern union {
2200 const enum_simple = ty.castTag(.enum_simple).?.data;2657 const enum_simple = ty.castTag(.enum_simple).?.data;
2201 return S.fieldWithRange(enum_tag, enum_simple.fields.count());2658 return S.fieldWithRange(enum_tag, enum_simple.fields.count());
2202 },2659 },
2660 .atomic_ordering,
2661 .atomic_rmw_op,
2662 .calling_convention,
2663 .float_mode,
2664 .reduce_op,
2665 .call_options,
2666 .export_options,
2667 .extern_options,
2668 => @panic("TODO resolve std.builtin types"),
2203 else => unreachable,2669 else => unreachable,
2204 }2670 }
2205 }2671 }
...@@ -2222,6 +2688,55 @@ pub const Type = extern union {...@@ -2222,6 +2688,55 @@ pub const Type = extern union {
2222 const error_set = ty.castTag(.error_set).?.data;2688 const error_set = ty.castTag(.error_set).?.data;
2223 return error_set.srcLoc();2689 return error_set.srcLoc();
2224 },2690 },
2691 .@"union", .union_tagged => {
2692 const union_obj = ty.cast(Payload.Union).?.data;
2693 return union_obj.srcLoc();
2694 },
2695 .atomic_ordering,
2696 .atomic_rmw_op,
2697 .calling_convention,
2698 .float_mode,
2699 .reduce_op,
2700 .call_options,
2701 .export_options,
2702 .extern_options,
2703 => @panic("TODO resolve std.builtin types"),
2704 else => unreachable,
2705 }
2706 }
2707
2708 pub fn getOwnerDecl(ty: Type) *Module.Decl {
2709 switch (ty.tag()) {
2710 .enum_full, .enum_nonexhaustive => {
2711 const enum_full = ty.cast(Payload.EnumFull).?.data;
2712 return enum_full.owner_decl;
2713 },
2714 .enum_simple => {
2715 const enum_simple = ty.castTag(.enum_simple).?.data;
2716 return enum_simple.owner_decl;
2717 },
2718 .@"struct" => {
2719 const struct_obj = ty.castTag(.@"struct").?.data;
2720 return struct_obj.owner_decl;
2721 },
2722 .error_set => {
2723 const error_set = ty.castTag(.error_set).?.data;
2724 return error_set.owner_decl;
2725 },
2726 .@"union", .union_tagged => {
2727 const union_obj = ty.cast(Payload.Union).?.data;
2728 return union_obj.owner_decl;
2729 },
2730 .@"opaque" => @panic("TODO"),
2731 .atomic_ordering,
2732 .atomic_rmw_op,
2733 .calling_convention,
2734 .float_mode,
2735 .reduce_op,
2736 .call_options,
2737 .export_options,
2738 .extern_options,
2739 => @panic("TODO resolve std.builtin types"),
2225 else => unreachable,2740 else => unreachable,
2226 }2741 }
2227 }2742 }
...@@ -2254,6 +2769,15 @@ pub const Type = extern union {...@@ -2254,6 +2769,15 @@ pub const Type = extern union {
2254 const enum_simple = ty.castTag(.enum_simple).?.data;2769 const enum_simple = ty.castTag(.enum_simple).?.data;
2255 return S.intInRange(int, enum_simple.fields.count());2770 return S.intInRange(int, enum_simple.fields.count());
2256 },2771 },
2772 .atomic_ordering,
2773 .atomic_rmw_op,
2774 .calling_convention,
2775 .float_mode,
2776 .reduce_op,
2777 .call_options,
2778 .export_options,
2779 .extern_options,
2780 => @panic("TODO resolve std.builtin types"),
22572781
2258 else => unreachable,2782 else => unreachable,
2259 }2783 }
...@@ -2300,16 +2824,27 @@ pub const Type = extern union {...@@ -2300,16 +2824,27 @@ pub const Type = extern union {
2300 comptime_int,2824 comptime_int,
2301 comptime_float,2825 comptime_float,
2302 noreturn,2826 noreturn,
2303 enum_literal,2827 @"anyframe",
2304 @"null",2828 @"null",
2305 @"undefined",2829 @"undefined",
2830 enum_literal,
2831 atomic_ordering,
2832 atomic_rmw_op,
2833 calling_convention,
2834 float_mode,
2835 reduce_op,
2836 call_options,
2837 export_options,
2838 extern_options,
2839 manyptr_u8,
2840 manyptr_const_u8,
2306 fn_noreturn_no_args,2841 fn_noreturn_no_args,
2307 fn_void_no_args,2842 fn_void_no_args,
2308 fn_naked_noreturn_no_args,2843 fn_naked_noreturn_no_args,
2309 fn_ccc_void_no_args,2844 fn_ccc_void_no_args,
2310 single_const_pointer_to_comptime_int,2845 single_const_pointer_to_comptime_int,
2311 anyerror_void_error_union,
2312 const_slice_u8,2846 const_slice_u8,
2847 anyerror_void_error_union,
2313 /// This is a special type for variadic parameters of a function call.2848 /// This is a special type for variadic parameters of a function call.
2314 /// Casts to it will validate that the type can be passed to a c calling convetion function.2849 /// Casts to it will validate that the type can be passed to a c calling convetion function.
2315 var_args_param,2850 var_args_param,
...@@ -2327,6 +2862,7 @@ pub const Type = extern union {...@@ -2327,6 +2862,7 @@ pub const Type = extern union {
2327 array_u8_sentinel_0,2862 array_u8_sentinel_0,
2328 array,2863 array,
2329 array_sentinel,2864 array_sentinel,
2865 vector,
2330 pointer,2866 pointer,
2331 single_const_pointer,2867 single_const_pointer,
2332 single_mut_pointer,2868 single_mut_pointer,
...@@ -2343,11 +2879,14 @@ pub const Type = extern union {...@@ -2343,11 +2879,14 @@ pub const Type = extern union {
2343 optional_single_mut_pointer,2879 optional_single_mut_pointer,
2344 optional_single_const_pointer,2880 optional_single_const_pointer,
2345 error_union,2881 error_union,
2882 anyframe_T,
2346 error_set,2883 error_set,
2347 error_set_single,2884 error_set_single,
2348 empty_struct,2885 empty_struct,
2349 @"opaque",2886 @"opaque",
2350 @"struct",2887 @"struct",
2888 @"union",
2889 union_tagged,
2351 enum_simple,2890 enum_simple,
2352 enum_full,2891 enum_full,
2353 enum_nonexhaustive,2892 enum_nonexhaustive,
...@@ -2404,6 +2943,17 @@ pub const Type = extern union {...@@ -2404,6 +2943,17 @@ pub const Type = extern union {
2404 .inferred_alloc_mut,2943 .inferred_alloc_mut,
2405 .var_args_param,2944 .var_args_param,
2406 .empty_struct_literal,2945 .empty_struct_literal,
2946 .manyptr_u8,
2947 .manyptr_const_u8,
2948 .atomic_ordering,
2949 .atomic_rmw_op,
2950 .calling_convention,
2951 .float_mode,
2952 .reduce_op,
2953 .call_options,
2954 .export_options,
2955 .extern_options,
2956 .@"anyframe",
2407 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),2957 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
24082958
2409 .array_u8,2959 .array_u8,
...@@ -2421,6 +2971,7 @@ pub const Type = extern union {...@@ -2421,6 +2971,7 @@ pub const Type = extern union {
2421 .optional,2971 .optional,
2422 .optional_single_mut_pointer,2972 .optional_single_mut_pointer,
2423 .optional_single_const_pointer,2973 .optional_single_const_pointer,
2974 .anyframe_T,
2424 => Payload.ElemType,2975 => Payload.ElemType,
24252976
2426 .int_signed,2977 .int_signed,
...@@ -2429,7 +2980,7 @@ pub const Type = extern union {...@@ -2429,7 +2980,7 @@ pub const Type = extern union {
24292980
2430 .error_set => Payload.ErrorSet,2981 .error_set => Payload.ErrorSet,
24312982
2432 .array => Payload.Array,2983 .array, .vector => Payload.Array,
2433 .array_sentinel => Payload.ArraySentinel,2984 .array_sentinel => Payload.ArraySentinel,
2434 .pointer => Payload.Pointer,2985 .pointer => Payload.Pointer,
2435 .function => Payload.Function,2986 .function => Payload.Function,
...@@ -2437,6 +2988,7 @@ pub const Type = extern union {...@@ -2437,6 +2988,7 @@ pub const Type = extern union {
2437 .error_set_single => Payload.Name,2988 .error_set_single => Payload.Name,
2438 .@"opaque" => Payload.Opaque,2989 .@"opaque" => Payload.Opaque,
2439 .@"struct" => Payload.Struct,2990 .@"struct" => Payload.Struct,
2991 .@"union", .union_tagged => Payload.Union,
2440 .enum_full, .enum_nonexhaustive => Payload.EnumFull,2992 .enum_full, .enum_nonexhaustive => Payload.EnumFull,
2441 .enum_simple => Payload.EnumSimple,2993 .enum_simple => Payload.EnumSimple,
2442 .empty_struct => Payload.ContainerScope,2994 .empty_struct => Payload.ContainerScope,
...@@ -2472,9 +3024,7 @@ pub const Type = extern union {...@@ -2472,9 +3024,7 @@ pub const Type = extern union {
2472 };3024 };
24733025
2474 pub const Array = struct {3026 pub const Array = struct {
2475 pub const base_tag = Tag.array;3027 base: Payload,
2476
2477 base: Payload = Payload{ .tag = base_tag },
2478 data: struct {3028 data: struct {
2479 len: u64,3029 len: u64,
2480 elem_type: Type,3030 elem_type: Type,
...@@ -2564,12 +3114,12 @@ pub const Type = extern union {...@@ -2564,12 +3114,12 @@ pub const Type = extern union {
2564 /// Most commonly used for files.3114 /// Most commonly used for files.
2565 pub const ContainerScope = struct {3115 pub const ContainerScope = struct {
2566 base: Payload,3116 base: Payload,
2567 data: *Module.Scope.Container,3117 data: *Module.Scope.Namespace,
2568 };3118 };
25693119
2570 pub const Opaque = struct {3120 pub const Opaque = struct {
2571 base: Payload = .{ .tag = .@"opaque" },3121 base: Payload = .{ .tag = .@"opaque" },
2572 data: Module.Scope.Container,3122 data: Module.Scope.Namespace,
2573 };3123 };
25743124
2575 pub const Struct = struct {3125 pub const Struct = struct {
...@@ -2577,6 +3127,11 @@ pub const Type = extern union {...@@ -2577,6 +3127,11 @@ pub const Type = extern union {
2577 data: *Module.Struct,3127 data: *Module.Struct,
2578 };3128 };
25793129
3130 pub const Union = struct {
3131 base: Payload,
3132 data: *Module.Union,
3133 };
3134
2580 pub const EnumFull = struct {3135 pub const EnumFull = struct {
2581 base: Payload,3136 base: Payload,
2582 data: *Module.EnumFull,3137 data: *Module.EnumFull,
src/value.zig+203-9
...@@ -55,15 +55,26 @@ pub const Value = extern union {...@@ -55,15 +55,26 @@ pub const Value = extern union {
55 comptime_int_type,55 comptime_int_type,
56 comptime_float_type,56 comptime_float_type,
57 noreturn_type,57 noreturn_type,
58 anyframe_type,
58 null_type,59 null_type,
59 undefined_type,60 undefined_type,
61 enum_literal_type,
62 atomic_ordering_type,
63 atomic_rmw_op_type,
64 calling_convention_type,
65 float_mode_type,
66 reduce_op_type,
67 call_options_type,
68 export_options_type,
69 extern_options_type,
70 manyptr_u8_type,
71 manyptr_const_u8_type,
60 fn_noreturn_no_args_type,72 fn_noreturn_no_args_type,
61 fn_void_no_args_type,73 fn_void_no_args_type,
62 fn_naked_noreturn_no_args_type,74 fn_naked_noreturn_no_args_type,
63 fn_ccc_void_no_args_type,75 fn_ccc_void_no_args_type,
64 single_const_pointer_to_comptime_int_type,76 single_const_pointer_to_comptime_int_type,
65 const_slice_u8_type,77 const_slice_u8_type,
66 enum_literal_type,
6778
68 undef,79 undef,
69 zero,80 zero,
...@@ -93,6 +104,7 @@ pub const Value = extern union {...@@ -93,6 +104,7 @@ pub const Value = extern union {
93 /// Represents a pointer to a decl, not the value of the decl.104 /// Represents a pointer to a decl, not the value of the decl.
94 decl_ref,105 decl_ref,
95 elem_ptr,106 elem_ptr,
107 field_ptr,
96 /// A slice of u8 whose memory is managed externally.108 /// A slice of u8 whose memory is managed externally.
97 bytes,109 bytes,
98 /// This value is repeated some number of times. The amount of times to repeat110 /// This value is repeated some number of times. The amount of times to repeat
...@@ -107,6 +119,10 @@ pub const Value = extern union {...@@ -107,6 +119,10 @@ pub const Value = extern union {
107 enum_field_index,119 enum_field_index,
108 @"error",120 @"error",
109 error_union,121 error_union,
122 /// An instance of a struct.
123 @"struct",
124 /// An instance of a union.
125 @"union",
110 /// This is a special value that tracks a set of types that have been stored126 /// This is a special value that tracks a set of types that have been stored
111 /// to an inferred allocation. It does not support any of the normal value queries.127 /// to an inferred allocation. It does not support any of the normal value queries.
112 inferred_alloc,128 inferred_alloc,
...@@ -156,6 +172,7 @@ pub const Value = extern union {...@@ -156,6 +172,7 @@ pub const Value = extern union {
156 .fn_naked_noreturn_no_args_type,172 .fn_naked_noreturn_no_args_type,
157 .fn_ccc_void_no_args_type,173 .fn_ccc_void_no_args_type,
158 .single_const_pointer_to_comptime_int_type,174 .single_const_pointer_to_comptime_int_type,
175 .anyframe_type,
159 .const_slice_u8_type,176 .const_slice_u8_type,
160 .enum_literal_type,177 .enum_literal_type,
161 .undef,178 .undef,
...@@ -169,6 +186,16 @@ pub const Value = extern union {...@@ -169,6 +186,16 @@ pub const Value = extern union {
169 .bool_true,186 .bool_true,
170 .bool_false,187 .bool_false,
171 .abi_align_default,188 .abi_align_default,
189 .manyptr_u8_type,
190 .manyptr_const_u8_type,
191 .atomic_ordering_type,
192 .atomic_rmw_op_type,
193 .calling_convention_type,
194 .float_mode_type,
195 .reduce_op_type,
196 .call_options_type,
197 .export_options_type,
198 .extern_options_type,
172 => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),199 => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
173200
174 .int_big_positive,201 .int_big_positive,
...@@ -197,12 +224,15 @@ pub const Value = extern union {...@@ -197,12 +224,15 @@ pub const Value = extern union {
197 .function => Payload.Function,224 .function => Payload.Function,
198 .variable => Payload.Variable,225 .variable => Payload.Variable,
199 .elem_ptr => Payload.ElemPtr,226 .elem_ptr => Payload.ElemPtr,
227 .field_ptr => Payload.FieldPtr,
200 .float_16 => Payload.Float_16,228 .float_16 => Payload.Float_16,
201 .float_32 => Payload.Float_32,229 .float_32 => Payload.Float_32,
202 .float_64 => Payload.Float_64,230 .float_64 => Payload.Float_64,
203 .float_128 => Payload.Float_128,231 .float_128 => Payload.Float_128,
204 .@"error" => Payload.Error,232 .@"error" => Payload.Error,
205 .inferred_alloc => Payload.InferredAlloc,233 .inferred_alloc => Payload.InferredAlloc,
234 .@"struct" => Payload.Struct,
235 .@"union" => Payload.Union,
206 };236 };
207 }237 }
208238
...@@ -314,6 +344,7 @@ pub const Value = extern union {...@@ -314,6 +344,7 @@ pub const Value = extern union {
314 .fn_naked_noreturn_no_args_type,344 .fn_naked_noreturn_no_args_type,
315 .fn_ccc_void_no_args_type,345 .fn_ccc_void_no_args_type,
316 .single_const_pointer_to_comptime_int_type,346 .single_const_pointer_to_comptime_int_type,
347 .anyframe_type,
317 .const_slice_u8_type,348 .const_slice_u8_type,
318 .enum_literal_type,349 .enum_literal_type,
319 .undef,350 .undef,
...@@ -327,6 +358,16 @@ pub const Value = extern union {...@@ -327,6 +358,16 @@ pub const Value = extern union {
327 .bool_false,358 .bool_false,
328 .empty_struct_value,359 .empty_struct_value,
329 .abi_align_default,360 .abi_align_default,
361 .manyptr_u8_type,
362 .manyptr_const_u8_type,
363 .atomic_ordering_type,
364 .atomic_rmw_op_type,
365 .calling_convention_type,
366 .float_mode_type,
367 .reduce_op_type,
368 .call_options_type,
369 .export_options_type,
370 .extern_options_type,
330 => unreachable,371 => unreachable,
331372
332 .ty => {373 .ty => {
...@@ -375,6 +416,18 @@ pub const Value = extern union {...@@ -375,6 +416,18 @@ pub const Value = extern union {
375 };416 };
376 return Value{ .ptr_otherwise = &new_payload.base };417 return Value{ .ptr_otherwise = &new_payload.base };
377 },418 },
419 .field_ptr => {
420 const payload = self.castTag(.field_ptr).?;
421 const new_payload = try allocator.create(Payload.FieldPtr);
422 new_payload.* = .{
423 .base = payload.base,
424 .data = .{
425 .container_ptr = try payload.data.container_ptr.copy(allocator),
426 .field_index = payload.data.field_index,
427 },
428 };
429 return Value{ .ptr_otherwise = &new_payload.base };
430 },
378 .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),431 .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),
379 .repeated => {432 .repeated => {
380 const payload = self.castTag(.repeated).?;433 const payload = self.castTag(.repeated).?;
...@@ -409,6 +462,8 @@ pub const Value = extern union {...@@ -409,6 +462,8 @@ pub const Value = extern union {
409 };462 };
410 return Value{ .ptr_otherwise = &new_payload.base };463 return Value{ .ptr_otherwise = &new_payload.base };
411 },464 },
465 .@"struct" => @panic("TODO can't copy struct value without knowing the type"),
466 .@"union" => @panic("TODO can't copy union value without knowing the type"),
412467
413 .inferred_alloc => unreachable,468 .inferred_alloc => unreachable,
414 }469 }
...@@ -472,11 +527,28 @@ pub const Value = extern union {...@@ -472,11 +527,28 @@ pub const Value = extern union {
472 .fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),527 .fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
473 .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"),528 .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"),
474 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),529 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
530 .anyframe_type => return out_stream.writeAll("anyframe"),
475 .const_slice_u8_type => return out_stream.writeAll("[]const u8"),531 .const_slice_u8_type => return out_stream.writeAll("[]const u8"),
476 .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"),532 .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"),
533 .manyptr_u8_type => return out_stream.writeAll("[*]u8"),
534 .manyptr_const_u8_type => return out_stream.writeAll("[*]const u8"),
535 .atomic_ordering_type => return out_stream.writeAll("std.builtin.AtomicOrdering"),
536 .atomic_rmw_op_type => return out_stream.writeAll("std.builtin.AtomicRmwOp"),
537 .calling_convention_type => return out_stream.writeAll("std.builtin.CallingConvention"),
538 .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"),
539 .reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"),
540 .call_options_type => return out_stream.writeAll("std.builtin.CallOptions"),
541 .export_options_type => return out_stream.writeAll("std.builtin.ExportOptions"),
542 .extern_options_type => return out_stream.writeAll("std.builtin.ExternOptions"),
477 .abi_align_default => return out_stream.writeAll("(default ABI alignment)"),543 .abi_align_default => return out_stream.writeAll("(default ABI alignment)"),
478544
479 .empty_struct_value => return out_stream.writeAll("struct {}{}"),545 .empty_struct_value => return out_stream.writeAll("struct {}{}"),
546 .@"struct" => {
547 return out_stream.writeAll("(struct value)");
548 },
549 .@"union" => {
550 return out_stream.writeAll("(union value)");
551 },
480 .null_value => return out_stream.writeAll("null"),552 .null_value => return out_stream.writeAll("null"),
481 .undef => return out_stream.writeAll("undefined"),553 .undef => return out_stream.writeAll("undefined"),
482 .zero => return out_stream.writeAll("0"),554 .zero => return out_stream.writeAll("0"),
...@@ -511,6 +583,11 @@ pub const Value = extern union {...@@ -511,6 +583,11 @@ pub const Value = extern union {
511 try out_stream.print("&[{}] ", .{elem_ptr.index});583 try out_stream.print("&[{}] ", .{elem_ptr.index});
512 val = elem_ptr.array_ptr;584 val = elem_ptr.array_ptr;
513 },585 },
586 .field_ptr => {
587 const field_ptr = val.castTag(.field_ptr).?.data;
588 try out_stream.print("fieldptr({d}) ", .{field_ptr.field_index});
589 val = field_ptr.container_ptr;
590 },
514 .empty_array => return out_stream.writeAll(".{}"),591 .empty_array => return out_stream.writeAll(".{}"),
515 .enum_literal => return out_stream.print(".{}", .{std.zig.fmtId(self.castTag(.enum_literal).?.data)}),592 .enum_literal => return out_stream.print(".{}", .{std.zig.fmtId(self.castTag(.enum_literal).?.data)}),
516 .enum_field_index => return out_stream.print("(enum field {d})", .{self.castTag(.enum_field_index).?.data}),593 .enum_field_index => return out_stream.print("(enum field {d})", .{self.castTag(.enum_field_index).?.data}),
...@@ -593,8 +670,19 @@ pub const Value = extern union {...@@ -593,8 +670,19 @@ pub const Value = extern union {
593 .fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args),670 .fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args),
594 .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args),671 .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args),
595 .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),672 .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
673 .anyframe_type => Type.initTag(.@"anyframe"),
596 .const_slice_u8_type => Type.initTag(.const_slice_u8),674 .const_slice_u8_type => Type.initTag(.const_slice_u8),
597 .enum_literal_type => Type.initTag(.enum_literal),675 .enum_literal_type => Type.initTag(.enum_literal),
676 .manyptr_u8_type => Type.initTag(.manyptr_u8),
677 .manyptr_const_u8_type => Type.initTag(.manyptr_const_u8),
678 .atomic_ordering_type => Type.initTag(.atomic_ordering),
679 .atomic_rmw_op_type => Type.initTag(.atomic_rmw_op),
680 .calling_convention_type => Type.initTag(.calling_convention),
681 .float_mode_type => Type.initTag(.float_mode),
682 .reduce_op_type => Type.initTag(.reduce_op),
683 .call_options_type => Type.initTag(.call_options),
684 .export_options_type => Type.initTag(.export_options),
685 .extern_options_type => Type.initTag(.extern_options),
598686
599 .int_type => {687 .int_type => {
600 const payload = self.castTag(.int_type).?.data;688 const payload = self.castTag(.int_type).?.data;
...@@ -627,6 +715,7 @@ pub const Value = extern union {...@@ -627,6 +715,7 @@ pub const Value = extern union {
627 .ref_val,715 .ref_val,
628 .decl_ref,716 .decl_ref,
629 .elem_ptr,717 .elem_ptr,
718 .field_ptr,
630 .bytes,719 .bytes,
631 .repeated,720 .repeated,
632 .float_16,721 .float_16,
...@@ -638,12 +727,23 @@ pub const Value = extern union {...@@ -638,12 +727,23 @@ pub const Value = extern union {
638 .@"error",727 .@"error",
639 .error_union,728 .error_union,
640 .empty_struct_value,729 .empty_struct_value,
730 .@"struct",
731 .@"union",
641 .inferred_alloc,732 .inferred_alloc,
642 .abi_align_default,733 .abi_align_default,
643 => unreachable,734 => unreachable,
644 };735 };
645 }736 }
646737
738 /// Asserts the type is an enum type.
739 pub fn toEnum(val: Value, enum_ty: Type, comptime E: type) E {
740 // TODO this needs to resolve other kinds of Value tags rather than
741 // assuming the tag will be .enum_field_index.
742 const field_index = val.castTag(.enum_field_index).?.data;
743 // TODO should `@intToEnum` do this `@intCast` for you?
744 return @intToEnum(E, @intCast(@typeInfo(E).Enum.tag_type, field_index));
745 }
746
647 /// Asserts the value is an integer.747 /// Asserts the value is an integer.
648 pub fn toBigInt(self: Value, space: *BigIntSpace) BigIntConst {748 pub fn toBigInt(self: Value, space: *BigIntSpace) BigIntConst {
649 switch (self.tag()) {749 switch (self.tag()) {
...@@ -930,7 +1030,11 @@ pub const Value = extern union {...@@ -930,7 +1030,11 @@ pub const Value = extern union {
9301030
931 /// Asserts the value is comparable.1031 /// Asserts the value is comparable.
932 pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value) bool {1032 pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value) bool {
933 return order(lhs, rhs).compare(op);1033 return switch (op) {
1034 .eq => lhs.eql(rhs),
1035 .neq => !lhs.eql(rhs),
1036 else => order(lhs, rhs).compare(op),
1037 };
934 }1038 }
9351039
936 /// Asserts the value is comparable.1040 /// Asserts the value is comparable.
...@@ -942,12 +1046,19 @@ pub const Value = extern union {...@@ -942,12 +1046,19 @@ pub const Value = extern union {
942 const a_tag = a.tag();1046 const a_tag = a.tag();
943 const b_tag = b.tag();1047 const b_tag = b.tag();
944 if (a_tag == b_tag) {1048 if (a_tag == b_tag) {
945 if (a_tag == .void_value or a_tag == .null_value) {1049 switch (a_tag) {
946 return true;1050 .void_value, .null_value => return true,
947 } else if (a_tag == .enum_literal) {1051 .enum_literal => {
948 const a_name = a.castTag(.enum_literal).?.data;1052 const a_name = a.castTag(.enum_literal).?.data;
949 const b_name = b.castTag(.enum_literal).?.data;1053 const b_name = b.castTag(.enum_literal).?.data;
950 return std.mem.eql(u8, a_name, b_name);1054 return std.mem.eql(u8, a_name, b_name);
1055 },
1056 .enum_field_index => {
1057 const a_field_index = a.castTag(.enum_field_index).?.data;
1058 const b_field_index = b.castTag(.enum_field_index).?.data;
1059 return a_field_index == b_field_index;
1060 },
1061 else => {},
951 }1062 }
952 }1063 }
953 if (a.isType() and b.isType()) {1064 if (a.isType() and b.isType()) {
...@@ -958,7 +1069,7 @@ pub const Value = extern union {...@@ -958,7 +1069,7 @@ pub const Value = extern union {
958 const b_type = b.toType(&fib.allocator) catch unreachable;1069 const b_type = b.toType(&fib.allocator) catch unreachable;
959 return a_type.eql(b_type);1070 return a_type.eql(b_type);
960 }1071 }
961 return compare(a, .eq, b);1072 return order(a, b).compare(.eq);
962 }1073 }
9631074
964 pub fn hash_u32(self: Value) u32 {1075 pub fn hash_u32(self: Value) u32 {
...@@ -1009,6 +1120,7 @@ pub const Value = extern union {...@@ -1009,6 +1120,7 @@ pub const Value = extern union {
1009 .fn_naked_noreturn_no_args_type,1120 .fn_naked_noreturn_no_args_type,
1010 .fn_ccc_void_no_args_type,1121 .fn_ccc_void_no_args_type,
1011 .single_const_pointer_to_comptime_int_type,1122 .single_const_pointer_to_comptime_int_type,
1123 .anyframe_type,
1012 .const_slice_u8_type,1124 .const_slice_u8_type,
1013 .enum_literal_type,1125 .enum_literal_type,
1014 .ty,1126 .ty,
...@@ -1096,6 +1208,11 @@ pub const Value = extern union {...@@ -1096,6 +1208,11 @@ pub const Value = extern union {
1096 std.hash.autoHash(&hasher, payload.array_ptr.hash());1208 std.hash.autoHash(&hasher, payload.array_ptr.hash());
1097 std.hash.autoHash(&hasher, payload.index);1209 std.hash.autoHash(&hasher, payload.index);
1098 },1210 },
1211 .field_ptr => {
1212 const payload = self.castTag(.field_ptr).?.data;
1213 std.hash.autoHash(&hasher, payload.container_ptr.hash());
1214 std.hash.autoHash(&hasher, payload.field_index);
1215 },
1099 .decl_ref => {1216 .decl_ref => {
1100 const decl = self.castTag(.decl_ref).?.data;1217 const decl = self.castTag(.decl_ref).?.data;
1101 std.hash.autoHash(&hasher, decl);1218 std.hash.autoHash(&hasher, decl);
...@@ -1121,6 +1238,20 @@ pub const Value = extern union {...@@ -1121,6 +1238,20 @@ pub const Value = extern union {
1121 std.hash.autoHash(&hasher, payload.hash());1238 std.hash.autoHash(&hasher, payload.hash());
1122 },1239 },
1123 .inferred_alloc => unreachable,1240 .inferred_alloc => unreachable,
1241
1242 .manyptr_u8_type,
1243 .manyptr_const_u8_type,
1244 .atomic_ordering_type,
1245 .atomic_rmw_op_type,
1246 .calling_convention_type,
1247 .float_mode_type,
1248 .reduce_op_type,
1249 .call_options_type,
1250 .export_options_type,
1251 .extern_options_type,
1252 .@"struct",
1253 .@"union",
1254 => @panic("TODO this hash function looks pretty broken. audit it"),
1124 }1255 }
1125 return hasher.final();1256 return hasher.final();
1126 }1257 }
...@@ -1136,6 +1267,11 @@ pub const Value = extern union {...@@ -1136,6 +1267,11 @@ pub const Value = extern union {
1136 const array_val = try elem_ptr.array_ptr.pointerDeref(allocator);1267 const array_val = try elem_ptr.array_ptr.pointerDeref(allocator);
1137 return array_val.elemValue(allocator, elem_ptr.index);1268 return array_val.elemValue(allocator, elem_ptr.index);
1138 },1269 },
1270 .field_ptr => {
1271 const field_ptr = self.castTag(.field_ptr).?.data;
1272 const container_val = try field_ptr.container_ptr.pointerDeref(allocator);
1273 return container_val.fieldValue(allocator, field_ptr.field_index);
1274 },
11391275
1140 else => unreachable,1276 else => unreachable,
1141 };1277 };
...@@ -1156,6 +1292,22 @@ pub const Value = extern union {...@@ -1156,6 +1292,22 @@ pub const Value = extern union {
1156 }1292 }
1157 }1293 }
11581294
1295 pub fn fieldValue(val: Value, allocator: *Allocator, index: usize) error{OutOfMemory}!Value {
1296 switch (val.tag()) {
1297 .@"struct" => {
1298 const field_values = val.castTag(.@"struct").?.data;
1299 return field_values[index];
1300 },
1301 .@"union" => {
1302 const payload = val.castTag(.@"union").?.data;
1303 // TODO assert the tag is correct
1304 return payload.val;
1305 },
1306
1307 else => unreachable,
1308 }
1309 }
1310
1159 /// Returns a pointer to the element value at the index.1311 /// Returns a pointer to the element value at the index.
1160 pub fn elemPtr(self: Value, allocator: *Allocator, index: usize) !Value {1312 pub fn elemPtr(self: Value, allocator: *Allocator, index: usize) !Value {
1161 if (self.castTag(.elem_ptr)) |elem_ptr| {1313 if (self.castTag(.elem_ptr)) |elem_ptr| {
...@@ -1265,8 +1417,19 @@ pub const Value = extern union {...@@ -1265,8 +1417,19 @@ pub const Value = extern union {
1265 .fn_naked_noreturn_no_args_type,1417 .fn_naked_noreturn_no_args_type,
1266 .fn_ccc_void_no_args_type,1418 .fn_ccc_void_no_args_type,
1267 .single_const_pointer_to_comptime_int_type,1419 .single_const_pointer_to_comptime_int_type,
1420 .anyframe_type,
1268 .const_slice_u8_type,1421 .const_slice_u8_type,
1269 .enum_literal_type,1422 .enum_literal_type,
1423 .manyptr_u8_type,
1424 .manyptr_const_u8_type,
1425 .atomic_ordering_type,
1426 .atomic_rmw_op_type,
1427 .calling_convention_type,
1428 .float_mode_type,
1429 .reduce_op_type,
1430 .call_options_type,
1431 .export_options_type,
1432 .extern_options_type,
1270 => true,1433 => true,
12711434
1272 .zero,1435 .zero,
...@@ -1284,6 +1447,7 @@ pub const Value = extern union {...@@ -1284,6 +1447,7 @@ pub const Value = extern union {
1284 .ref_val,1447 .ref_val,
1285 .decl_ref,1448 .decl_ref,
1286 .elem_ptr,1449 .elem_ptr,
1450 .field_ptr,
1287 .bytes,1451 .bytes,
1288 .repeated,1452 .repeated,
1289 .float_16,1453 .float_16,
...@@ -1296,6 +1460,8 @@ pub const Value = extern union {...@@ -1296,6 +1460,8 @@ pub const Value = extern union {
1296 .@"error",1460 .@"error",
1297 .error_union,1461 .error_union,
1298 .empty_struct_value,1462 .empty_struct_value,
1463 .@"struct",
1464 .@"union",
1299 .null_value,1465 .null_value,
1300 .abi_align_default,1466 .abi_align_default,
1301 => false,1467 => false,
...@@ -1369,6 +1535,16 @@ pub const Value = extern union {...@@ -1369,6 +1535,16 @@ pub const Value = extern union {
1369 },1535 },
1370 };1536 };
13711537
1538 pub const FieldPtr = struct {
1539 pub const base_tag = Tag.field_ptr;
1540
1541 base: Payload = Payload{ .tag = base_tag },
1542 data: struct {
1543 container_ptr: Value,
1544 field_index: usize,
1545 },
1546 };
1547
1372 pub const Bytes = struct {1548 pub const Bytes = struct {
1373 base: Payload,1549 base: Payload,
1374 data: []const u8,1550 data: []const u8,
...@@ -1439,6 +1615,24 @@ pub const Value = extern union {...@@ -1439,6 +1615,24 @@ pub const Value = extern union {
1439 stored_inst_list: std.ArrayListUnmanaged(*ir.Inst) = .{},1615 stored_inst_list: std.ArrayListUnmanaged(*ir.Inst) = .{},
1440 },1616 },
1441 };1617 };
1618
1619 pub const Struct = struct {
1620 pub const base_tag = Tag.@"struct";
1621
1622 base: Payload = .{ .tag = base_tag },
1623 /// Field values. The number and type are according to the struct type.
1624 data: [*]Value,
1625 };
1626
1627 pub const Union = struct {
1628 pub const base_tag = Tag.@"union";
1629
1630 base: Payload = .{ .tag = base_tag },
1631 data: struct {
1632 tag: Value,
1633 val: Value,
1634 },
1635 };
1442 };1636 };
14431637
1444 /// Big enough to fit any non-BigInt value1638 /// Big enough to fit any non-BigInt value
src/zir.zig deleted-2439
...@@ -1,2439 +0,0 @@
1//! Zig Intermediate Representation. Astgen.zig converts AST nodes to these
2//! untyped IR instructions. Next, Sema.zig processes these into TZIR.
3
4const std = @import("std");
5const mem = std.mem;
6const Allocator = std.mem.Allocator;
7const assert = std.debug.assert;
8const BigIntConst = std.math.big.int.Const;
9const BigIntMutable = std.math.big.int.Mutable;
10const ast = std.zig.ast;
11
12const Type = @import("type.zig").Type;
13const Value = @import("value.zig").Value;
14const TypedValue = @import("TypedValue.zig");
15const ir = @import("ir.zig");
16const Module = @import("Module.zig");
17const LazySrcLoc = Module.LazySrcLoc;
18
19/// The minimum amount of information needed to represent a list of ZIR instructions.
20/// Once this structure is completed, it can be used to generate TZIR, followed by
21/// machine code, without any memory access into the AST tree token list, node list,
22/// or source bytes. Exceptions include:
23/// * Compile errors, which may need to reach into these data structures to
24/// create a useful report.
25/// * In the future, possibly inline assembly, which needs to get parsed and
26/// handled by the codegen backend, and errors reported there. However for now,
27/// inline assembly is not an exception.
28pub const Code = struct {
29 /// There is always implicitly a `block` instruction at index 0.
30 /// This is so that `break_inline` can break from the root block.
31 instructions: std.MultiArrayList(Inst).Slice,
32 /// In order to store references to strings in fewer bytes, we copy all
33 /// string bytes into here. String bytes can be null. It is up to whomever
34 /// is referencing the data here whether they want to store both index and length,
35 /// thus allowing null bytes, or store only index, and use null-termination. The
36 /// `string_bytes` array is agnostic to either usage.
37 string_bytes: []u8,
38 /// The meaning of this data is determined by `Inst.Tag` value.
39 extra: []u32,
40
41 /// Returns the requested data, as well as the new index which is at the start of the
42 /// trailers for the object.
43 pub fn extraData(code: Code, comptime T: type, index: usize) struct { data: T, end: usize } {
44 const fields = std.meta.fields(T);
45 var i: usize = index;
46 var result: T = undefined;
47 inline for (fields) |field| {
48 @field(result, field.name) = switch (field.field_type) {
49 u32 => code.extra[i],
50 Inst.Ref => @intToEnum(Inst.Ref, code.extra[i]),
51 else => unreachable,
52 };
53 i += 1;
54 }
55 return .{
56 .data = result,
57 .end = i,
58 };
59 }
60
61 /// Given an index into `string_bytes` returns the null-terminated string found there.
62 pub fn nullTerminatedString(code: Code, index: usize) [:0]const u8 {
63 var end: usize = index;
64 while (code.string_bytes[end] != 0) {
65 end += 1;
66 }
67 return code.string_bytes[index..end :0];
68 }
69
70 pub fn refSlice(code: Code, start: usize, len: usize) []Inst.Ref {
71 const raw_slice = code.extra[start..][0..len];
72 return @bitCast([]Inst.Ref, raw_slice);
73 }
74
75 pub fn deinit(code: *Code, gpa: *Allocator) void {
76 code.instructions.deinit(gpa);
77 gpa.free(code.string_bytes);
78 gpa.free(code.extra);
79 code.* = undefined;
80 }
81
82 /// For debugging purposes, like dumpFn but for unanalyzed zir blocks
83 pub fn dump(
84 code: Code,
85 gpa: *Allocator,
86 kind: []const u8,
87 scope: *Module.Scope,
88 param_count: usize,
89 ) !void {
90 var arena = std.heap.ArenaAllocator.init(gpa);
91 defer arena.deinit();
92
93 var writer: Writer = .{
94 .gpa = gpa,
95 .arena = &arena.allocator,
96 .scope = scope,
97 .code = code,
98 .indent = 0,
99 .param_count = param_count,
100 };
101
102 const decl_name = scope.srcDecl().?.name;
103 const stderr = std.io.getStdErr().writer();
104 try stderr.print("ZIR {s} {s} %0 ", .{ kind, decl_name });
105 try writer.writeInstToStream(stderr, 0);
106 try stderr.print(" // end ZIR {s} {s}\n\n", .{ kind, decl_name });
107 }
108};
109
110/// These are untyped instructions generated from an Abstract Syntax Tree.
111/// The data here is immutable because it is possible to have multiple
112/// analyses on the same ZIR happening at the same time.
113pub const Inst = struct {
114 tag: Tag,
115 data: Data,
116
117 /// These names are used directly as the instruction names in the text format.
118 pub const Tag = enum(u8) {
119 /// Arithmetic addition, asserts no integer overflow.
120 /// Uses the `pl_node` union field. Payload is `Bin`.
121 add,
122 /// Twos complement wrapping integer addition.
123 /// Uses the `pl_node` union field. Payload is `Bin`.
124 addwrap,
125 /// Allocates stack local memory.
126 /// Uses the `un_node` union field. The operand is the type of the allocated object.
127 /// The node source location points to a var decl node.
128 /// Indicates the beginning of a new statement in debug info.
129 alloc,
130 /// Same as `alloc` except mutable.
131 alloc_mut,
132 /// Same as `alloc` except the type is inferred.
133 /// Uses the `node` union field.
134 alloc_inferred,
135 /// Same as `alloc_inferred` except mutable.
136 alloc_inferred_mut,
137 /// Array concatenation. `a ++ b`
138 /// Uses the `pl_node` union field. Payload is `Bin`.
139 array_cat,
140 /// Array multiplication `a ** b`
141 /// Uses the `pl_node` union field. Payload is `Bin`.
142 array_mul,
143 /// `[N]T` syntax. No source location provided.
144 /// Uses the `bin` union field. lhs is length, rhs is element type.
145 array_type,
146 /// `[N:S]T` syntax. No source location provided.
147 /// Uses the `array_type_sentinel` field.
148 array_type_sentinel,
149 /// Given a pointer to an indexable object, returns the len property. This is
150 /// used by for loops. This instruction also emits a for-loop specific compile
151 /// error if the indexable object is not indexable.
152 /// Uses the `un_node` field. The AST node is the for loop node.
153 indexable_ptr_len,
154 /// Type coercion. No source location attached.
155 /// Uses the `bin` field.
156 as,
157 /// Type coercion to the function's return type.
158 /// Uses the `pl_node` field. Payload is `As`. AST node could be many things.
159 as_node,
160 /// Inline assembly. Non-volatile.
161 /// Uses the `pl_node` union field. Payload is `Asm`. AST node is the assembly node.
162 @"asm",
163 /// Inline assembly with the volatile attribute.
164 /// Uses the `pl_node` union field. Payload is `Asm`. AST node is the assembly node.
165 asm_volatile,
166 /// Bitwise AND. `&`
167 bit_and,
168 /// Bitcast a value to a different type.
169 /// Uses the pl_node field with payload `Bin`.
170 bitcast,
171 /// A typed result location pointer is bitcasted to a new result location pointer.
172 /// The new result location pointer has an inferred type.
173 /// Uses the un_node field.
174 bitcast_result_ptr,
175 /// Bitwise NOT. `~`
176 /// Uses `un_node`.
177 bit_not,
178 /// Bitwise OR. `|`
179 bit_or,
180 /// A labeled block of code, which can return a value.
181 /// Uses the `pl_node` union field. Payload is `Block`.
182 block,
183 /// A list of instructions which are analyzed in the parent context, without
184 /// generating a runtime block. Must terminate with an "inline" variant of
185 /// a noreturn instruction.
186 /// Uses the `pl_node` union field. Payload is `Block`.
187 block_inline,
188 /// Boolean AND. See also `bit_and`.
189 /// Uses the `pl_node` union field. Payload is `Bin`.
190 bool_and,
191 /// Boolean NOT. See also `bit_not`.
192 /// Uses the `un_node` field.
193 bool_not,
194 /// Boolean OR. See also `bit_or`.
195 /// Uses the `pl_node` union field. Payload is `Bin`.
196 bool_or,
197 /// Short-circuiting boolean `and`. `lhs` is a boolean `Ref` and the other operand
198 /// is a block, which is evaluated if `lhs` is `true`.
199 /// Uses the `bool_br` union field.
200 bool_br_and,
201 /// Short-circuiting boolean `or`. `lhs` is a boolean `Ref` and the other operand
202 /// is a block, which is evaluated if `lhs` is `false`.
203 /// Uses the `bool_br` union field.
204 bool_br_or,
205 /// Return a value from a block.
206 /// Uses the `break` union field.
207 /// Uses the source information from previous instruction.
208 @"break",
209 /// Return a value from a block. This instruction is used as the terminator
210 /// of a `block_inline`. It allows using the return value from `Sema.analyzeBody`.
211 /// This instruction may also be used when it is known that there is only one
212 /// break instruction in a block, and the target block is the parent.
213 /// Uses the `break` union field.
214 break_inline,
215 /// Uses the `node` union field.
216 breakpoint,
217 /// Function call with modifier `.auto`.
218 /// Uses `pl_node`. AST node is the function call. Payload is `Call`.
219 call,
220 /// Same as `call` but it also does `ensure_result_used` on the return value.
221 call_chkused,
222 /// Same as `call` but with modifier `.compile_time`.
223 call_compile_time,
224 /// Function call with modifier `.auto`, empty parameter list.
225 /// Uses the `un_node` field. Operand is callee. AST node is the function call.
226 call_none,
227 /// Same as `call_none` but it also does `ensure_result_used` on the return value.
228 call_none_chkused,
229 /// `<`
230 /// Uses the `pl_node` union field. Payload is `Bin`.
231 cmp_lt,
232 /// `<=`
233 /// Uses the `pl_node` union field. Payload is `Bin`.
234 cmp_lte,
235 /// `==`
236 /// Uses the `pl_node` union field. Payload is `Bin`.
237 cmp_eq,
238 /// `>=`
239 /// Uses the `pl_node` union field. Payload is `Bin`.
240 cmp_gte,
241 /// `>`
242 /// Uses the `pl_node` union field. Payload is `Bin`.
243 cmp_gt,
244 /// `!=`
245 /// Uses the `pl_node` union field. Payload is `Bin`.
246 cmp_neq,
247 /// Coerces a result location pointer to a new element type. It is evaluated "backwards"-
248 /// as type coercion from the new element type to the old element type.
249 /// Uses the `bin` union field.
250 /// LHS is destination element type, RHS is result pointer.
251 coerce_result_ptr,
252 /// Emit an error message and fail compilation.
253 /// Uses the `un_node` field.
254 compile_error,
255 /// Log compile time variables and emit an error message.
256 /// Uses the `pl_node` union field. The AST node is the compile log builtin call.
257 /// The payload is `MultiOp`.
258 compile_log,
259 /// Conditional branch. Splits control flow based on a boolean condition value.
260 /// Uses the `pl_node` union field. AST node is an if, while, for, etc.
261 /// Payload is `CondBr`.
262 condbr,
263 /// Same as `condbr`, except the condition is coerced to a comptime value, and
264 /// only the taken branch is analyzed. The then block and else block must
265 /// terminate with an "inline" variant of a noreturn instruction.
266 condbr_inline,
267 /// A struct type definition. Contains references to ZIR instructions for
268 /// the field types, defaults, and alignments.
269 /// Uses the `pl_node` union field. Payload is `StructDecl`.
270 struct_decl,
271 /// Same as `struct_decl`, except has the `packed` layout.
272 struct_decl_packed,
273 /// Same as `struct_decl`, except has the `extern` layout.
274 struct_decl_extern,
275 /// A union type definition. Contains references to ZIR instructions for
276 /// the field types and optional type tag expression.
277 /// Uses the `pl_node` union field. Payload is `UnionDecl`.
278 union_decl,
279 /// An enum type definition. Contains references to ZIR instructions for
280 /// the field value expressions and optional type tag expression.
281 /// Uses the `pl_node` union field. Payload is `EnumDecl`.
282 enum_decl,
283 /// Same as `enum_decl`, except the enum is non-exhaustive.
284 enum_decl_nonexhaustive,
285 /// An opaque type definition. Provides an AST node only.
286 /// Uses the `node` union field.
287 opaque_decl,
288 /// Declares the beginning of a statement. Used for debug info.
289 /// Uses the `node` union field.
290 dbg_stmt_node,
291 /// Represents a pointer to a global decl.
292 /// Uses the `pl_node` union field. `payload_index` is into `decls`.
293 decl_ref,
294 /// Equivalent to a decl_ref followed by load.
295 /// Uses the `pl_node` union field. `payload_index` is into `decls`.
296 decl_val,
297 /// Load the value from a pointer. Assumes `x.*` syntax.
298 /// Uses `un_node` field. AST node is the `x.*` syntax.
299 load,
300 /// Arithmetic division. Asserts no integer overflow.
301 /// Uses the `pl_node` union field. Payload is `Bin`.
302 div,
303 /// Given a pointer to an array, slice, or pointer, returns a pointer to the element at
304 /// the provided index. Uses the `bin` union field. Source location is implied
305 /// to be the same as the previous instruction.
306 elem_ptr,
307 /// Same as `elem_ptr` except also stores a source location node.
308 /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
309 elem_ptr_node,
310 /// Given an array, slice, or pointer, returns the element at the provided index.
311 /// Uses the `bin` union field. Source location is implied to be the same
312 /// as the previous instruction.
313 elem_val,
314 /// Same as `elem_val` except also stores a source location node.
315 /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
316 elem_val_node,
317 /// This instruction has been deleted late in the astgen phase. It must
318 /// be ignored, and the corresponding `Data` is undefined.
319 elided,
320 /// Emits a compile error if the operand is not `void`.
321 /// Uses the `un_node` field.
322 ensure_result_used,
323 /// Emits a compile error if an error is ignored.
324 /// Uses the `un_node` field.
325 ensure_result_non_error,
326 /// Create a `E!T` type.
327 /// Uses the `pl_node` field with `Bin` payload.
328 error_union_type,
329 /// `error.Foo` syntax. Uses the `str_tok` field of the Data union.
330 error_value,
331 /// Implements the `@export` builtin function.
332 /// Uses the `pl_node` union field. Payload is `Bin`.
333 @"export",
334 /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
335 /// to the named field. The field name is stored in string_bytes. Used by a.b syntax.
336 /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field.
337 field_ptr,
338 /// Given a struct or object that contains virtual fields, returns the named field.
339 /// The field name is stored in string_bytes. Used by a.b syntax.
340 /// This instruction also accepts a pointer.
341 /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field.
342 field_val,
343 /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
344 /// to the named field. The field name is a comptime instruction. Used by @field.
345 /// Uses `pl_node` field. The AST node is the builtin call. Payload is FieldNamed.
346 field_ptr_named,
347 /// Given a struct or object that contains virtual fields, returns the named field.
348 /// The field name is a comptime instruction. Used by @field.
349 /// Uses `pl_node` field. The AST node is the builtin call. Payload is FieldNamed.
350 field_val_named,
351 /// Convert a larger float type to any other float type, possibly causing
352 /// a loss of precision.
353 /// Uses the `pl_node` field. AST is the `@floatCast` syntax.
354 /// Payload is `Bin` with lhs as the dest type, rhs the operand.
355 floatcast,
356 /// Returns a function type, assuming unspecified calling convention.
357 /// Uses the `pl_node` union field. `payload_index` points to a `FnType`.
358 fn_type,
359 /// Same as `fn_type` but the function is variadic.
360 fn_type_var_args,
361 /// Returns a function type, with a calling convention instruction operand.
362 /// Uses the `pl_node` union field. `payload_index` points to a `FnTypeCc`.
363 fn_type_cc,
364 /// Same as `fn_type_cc` but the function is variadic.
365 fn_type_cc_var_args,
366 /// Implements the `@hasDecl` builtin.
367 /// Uses the `pl_node` union field. Payload is `Bin`.
368 has_decl,
369 /// `@import(operand)`.
370 /// Uses the `un_node` field.
371 import,
372 /// Integer literal that fits in a u64. Uses the int union value.
373 int,
374 /// A float literal that fits in a f32. Uses the float union value.
375 float,
376 /// A float literal that fits in a f128. Uses the `pl_node` union value.
377 /// Payload is `Float128`.
378 float128,
379 /// Convert an integer value to another integer type, asserting that the destination type
380 /// can hold the same mathematical value.
381 /// Uses the `pl_node` field. AST is the `@intCast` syntax.
382 /// Payload is `Bin` with lhs as the dest type, rhs the operand.
383 intcast,
384 /// Make an integer type out of signedness and bit count.
385 /// Payload is `int_type`
386 int_type,
387 /// Convert an error type to `u16`
388 error_to_int,
389 /// Convert a `u16` to `anyerror`
390 int_to_error,
391 /// Return a boolean false if an optional is null. `x != null`
392 /// Uses the `un_node` field.
393 is_non_null,
394 /// Return a boolean true if an optional is null. `x == null`
395 /// Uses the `un_node` field.
396 is_null,
397 /// Return a boolean false if an optional is null. `x.* != null`
398 /// Uses the `un_node` field.
399 is_non_null_ptr,
400 /// Return a boolean true if an optional is null. `x.* == null`
401 /// Uses the `un_node` field.
402 is_null_ptr,
403 /// Return a boolean true if value is an error
404 /// Uses the `un_node` field.
405 is_err,
406 /// Return a boolean true if dereferenced pointer is an error
407 /// Uses the `un_node` field.
408 is_err_ptr,
409 /// A labeled block of code that loops forever. At the end of the body will have either
410 /// a `repeat` instruction or a `repeat_inline` instruction.
411 /// Uses the `pl_node` field. The AST node is either a for loop or while loop.
412 /// This ZIR instruction is needed because TZIR does not (yet?) match ZIR, and Sema
413 /// needs to emit more than 1 TZIR block for this instruction.
414 /// The payload is `Block`.
415 loop,
416 /// Sends runtime control flow back to the beginning of the current block.
417 /// Uses the `node` field.
418 repeat,
419 /// Sends comptime control flow back to the beginning of the current block.
420 /// Uses the `node` field.
421 repeat_inline,
422 /// Merge two error sets into one, `E1 || E2`.
423 /// Uses the `pl_node` field with payload `Bin`.
424 merge_error_sets,
425 /// Ambiguously remainder division or modulus. If the computation would possibly have
426 /// a different value depending on whether the operation is remainder division or modulus,
427 /// a compile error is emitted. Otherwise the computation is performed.
428 /// Uses the `pl_node` union field. Payload is `Bin`.
429 mod_rem,
430 /// Arithmetic multiplication. Asserts no integer overflow.
431 /// Uses the `pl_node` union field. Payload is `Bin`.
432 mul,
433 /// Twos complement wrapping integer multiplication.
434 /// Uses the `pl_node` union field. Payload is `Bin`.
435 mulwrap,
436 /// Given a reference to a function and a parameter index, returns the
437 /// type of the parameter. The only usage of this instruction is for the
438 /// result location of parameters of function calls. In the case of a function's
439 /// parameter type being `anytype`, it is the type coercion's job to detect this
440 /// scenario and skip the coercion, so that semantic analysis of this instruction
441 /// is not in a position where it must create an invalid type.
442 /// Uses the `param_type` union field.
443 param_type,
444 /// Convert a pointer to a `usize` integer.
445 /// Uses the `un_node` field. The AST node is the builtin fn call node.
446 ptrtoint,
447 /// Turns an R-Value into a const L-Value. In other words, it takes a value,
448 /// stores it in a memory location, and returns a const pointer to it. If the value
449 /// is `comptime`, the memory location is global static constant data. Otherwise,
450 /// the memory location is in the stack frame, local to the scope containing the
451 /// instruction.
452 /// Uses the `un_tok` union field.
453 ref,
454 /// Obtains a pointer to the return value.
455 /// Uses the `node` union field.
456 ret_ptr,
457 /// Obtains the return type of the in-scope function.
458 /// Uses the `node` union field.
459 ret_type,
460 /// Sends control flow back to the function's callee.
461 /// Includes an operand as the return value.
462 /// Includes an AST node source location.
463 /// Uses the `un_node` union field.
464 ret_node,
465 /// Sends control flow back to the function's callee.
466 /// Includes an operand as the return value.
467 /// Includes a token source location.
468 /// Uses the `un_tok` union field.
469 ret_tok,
470 /// Same as `ret_tok` except the operand needs to get coerced to the function's
471 /// return type.
472 ret_coerce,
473 /// Changes the maximum number of backwards branches that compile-time
474 /// code execution can use before giving up and making a compile error.
475 /// Uses the `un_node` union field.
476 set_eval_branch_quota,
477 /// Integer shift-left. Zeroes are shifted in from the right hand side.
478 /// Uses the `pl_node` union field. Payload is `Bin`.
479 shl,
480 /// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type.
481 /// Uses the `pl_node` union field. Payload is `Bin`.
482 shr,
483 /// Create a pointer type that does not have a sentinel, alignment, or bit range specified.
484 /// Uses the `ptr_type_simple` union field.
485 ptr_type_simple,
486 /// Create a pointer type which can have a sentinel, alignment, and/or bit range.
487 /// Uses the `ptr_type` union field.
488 ptr_type,
489 /// Each `store_to_inferred_ptr` puts the type of the stored value into a set,
490 /// and then `resolve_inferred_alloc` triggers peer type resolution on the set.
491 /// The operand is a `alloc_inferred` or `alloc_inferred_mut` instruction, which
492 /// is the allocation that needs to have its type inferred.
493 /// Uses the `un_node` field. The AST node is the var decl.
494 resolve_inferred_alloc,
495 /// Slice operation `lhs[rhs..]`. No sentinel and no end offset.
496 /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceStart`.
497 slice_start,
498 /// Slice operation `array_ptr[start..end]`. No sentinel.
499 /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceEnd`.
500 slice_end,
501 /// Slice operation `array_ptr[start..end:sentinel]`.
502 /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceSentinel`.
503 slice_sentinel,
504 /// Write a value to a pointer. For loading, see `load`.
505 /// Source location is assumed to be same as previous instruction.
506 /// Uses the `bin` union field.
507 store,
508 /// Same as `store` except provides a source location.
509 /// Uses the `pl_node` union field. Payload is `Bin`.
510 store_node,
511 /// Same as `store` but the type of the value being stored will be used to infer
512 /// the block type. The LHS is the pointer to store to.
513 /// Uses the `bin` union field.
514 store_to_block_ptr,
515 /// Same as `store` but the type of the value being stored will be used to infer
516 /// the pointer type.
517 /// Uses the `bin` union field - Astgen.zig depends on the ability to change
518 /// the tag of an instruction from `store_to_block_ptr` to `store_to_inferred_ptr`
519 /// without changing the data.
520 store_to_inferred_ptr,
521 /// String Literal. Makes an anonymous Decl and then takes a pointer to it.
522 /// Uses the `str` union field.
523 str,
524 /// Arithmetic subtraction. Asserts no integer overflow.
525 /// Uses the `pl_node` union field. Payload is `Bin`.
526 sub,
527 /// Twos complement wrapping integer subtraction.
528 /// Uses the `pl_node` union field. Payload is `Bin`.
529 subwrap,
530 /// Arithmetic negation. Asserts no integer overflow.
531 /// Same as sub with a lhs of 0, split into a separate instruction to save memory.
532 /// Uses `un_node`.
533 negate,
534 /// Twos complement wrapping integer negation.
535 /// Same as subwrap with a lhs of 0, split into a separate instruction to save memory.
536 /// Uses `un_node`.
537 negate_wrap,
538 /// Returns the type of a value.
539 /// Uses the `un_tok` field.
540 typeof,
541 /// Given a value which is a pointer, returns the element type.
542 /// Uses the `un_node` field.
543 typeof_elem,
544 /// The builtin `@TypeOf` which returns the type after Peer Type Resolution
545 /// of one or more params.
546 /// Uses the `pl_node` field. AST node is the `@TypeOf` call. Payload is `MultiOp`.
547 typeof_peer,
548 /// Asserts control-flow will not reach this instruction (`unreachable`).
549 /// Uses the `unreachable` union field.
550 @"unreachable",
551 /// Bitwise XOR. `^`
552 /// Uses the `pl_node` union field. Payload is `Bin`.
553 xor,
554 /// Create an optional type '?T'
555 /// Uses the `un_node` field.
556 optional_type,
557 /// Create an optional type '?T'. The operand is a pointer value. The optional type will
558 /// be the type of the pointer element, wrapped in an optional.
559 /// Uses the `un_node` field.
560 optional_type_from_ptr_elem,
561 /// ?T => T with safety.
562 /// Given an optional value, returns the payload value, with a safety check that
563 /// the value is non-null. Used for `orelse`, `if` and `while`.
564 /// Uses the `un_node` field.
565 optional_payload_safe,
566 /// ?T => T without safety.
567 /// Given an optional value, returns the payload value. No safety checks.
568 /// Uses the `un_node` field.
569 optional_payload_unsafe,
570 /// *?T => *T with safety.
571 /// Given a pointer to an optional value, returns a pointer to the payload value,
572 /// with a safety check that the value is non-null. Used for `orelse`, `if` and `while`.
573 /// Uses the `un_node` field.
574 optional_payload_safe_ptr,
575 /// *?T => *T without safety.
576 /// Given a pointer to an optional value, returns a pointer to the payload value.
577 /// No safety checks.
578 /// Uses the `un_node` field.
579 optional_payload_unsafe_ptr,
580 /// E!T => T with safety.
581 /// Given an error union value, returns the payload value, with a safety check
582 /// that the value is not an error. Used for catch, if, and while.
583 /// Uses the `un_node` field.
584 err_union_payload_safe,
585 /// E!T => T without safety.
586 /// Given an error union value, returns the payload value. No safety checks.
587 /// Uses the `un_node` field.
588 err_union_payload_unsafe,
589 /// *E!T => *T with safety.
590 /// Given a pointer to an error union value, returns a pointer to the payload value,
591 /// with a safety check that the value is not an error. Used for catch, if, and while.
592 /// Uses the `un_node` field.
593 err_union_payload_safe_ptr,
594 /// *E!T => *T without safety.
595 /// Given a pointer to a error union value, returns a pointer to the payload value.
596 /// No safety checks.
597 /// Uses the `un_node` field.
598 err_union_payload_unsafe_ptr,
599 /// E!T => E without safety.
600 /// Given an error union value, returns the error code. No safety checks.
601 /// Uses the `un_node` field.
602 err_union_code,
603 /// *E!T => E without safety.
604 /// Given a pointer to an error union value, returns the error code. No safety checks.
605 /// Uses the `un_node` field.
606 err_union_code_ptr,
607 /// Takes a *E!T and raises a compiler error if T != void
608 /// Uses the `un_tok` field.
609 ensure_err_payload_void,
610 /// An enum literal. Uses the `str_tok` union field.
611 enum_literal,
612 /// An enum literal 8 or fewer bytes. No source location.
613 /// Uses the `small_str` field.
614 enum_literal_small,
615 /// A switch expression. Uses the `pl_node` union field.
616 /// AST node is the switch, payload is `SwitchBlock`.
617 /// All prongs of target handled.
618 switch_block,
619 /// Same as switch_block, except one or more prongs have multiple items.
620 switch_block_multi,
621 /// Same as switch_block, except has an else prong.
622 switch_block_else,
623 /// Same as switch_block_else, except one or more prongs have multiple items.
624 switch_block_else_multi,
625 /// Same as switch_block, except has an underscore prong.
626 switch_block_under,
627 /// Same as switch_block, except one or more prongs have multiple items.
628 switch_block_under_multi,
629 /// Same as `switch_block` but the target is a pointer to the value being switched on.
630 switch_block_ref,
631 /// Same as `switch_block_multi` but the target is a pointer to the value being switched on.
632 switch_block_ref_multi,
633 /// Same as `switch_block_else` but the target is a pointer to the value being switched on.
634 switch_block_ref_else,
635 /// Same as `switch_block_else_multi` but the target is a pointer to the
636 /// value being switched on.
637 switch_block_ref_else_multi,
638 /// Same as `switch_block_under` but the target is a pointer to the value
639 /// being switched on.
640 switch_block_ref_under,
641 /// Same as `switch_block_under_multi` but the target is a pointer to
642 /// the value being switched on.
643 switch_block_ref_under_multi,
644 /// Produces the capture value for a switch prong.
645 /// Uses the `switch_capture` field.
646 switch_capture,
647 /// Produces the capture value for a switch prong.
648 /// Result is a pointer to the value.
649 /// Uses the `switch_capture` field.
650 switch_capture_ref,
651 /// Produces the capture value for a switch prong.
652 /// The prong is one of the multi cases.
653 /// Uses the `switch_capture` field.
654 switch_capture_multi,
655 /// Produces the capture value for a switch prong.
656 /// The prong is one of the multi cases.
657 /// Result is a pointer to the value.
658 /// Uses the `switch_capture` field.
659 switch_capture_multi_ref,
660 /// Produces the capture value for the else/'_' switch prong.
661 /// Uses the `switch_capture` field.
662 switch_capture_else,
663 /// Produces the capture value for the else/'_' switch prong.
664 /// Result is a pointer to the value.
665 /// Uses the `switch_capture` field.
666 switch_capture_else_ref,
667 /// Given a set of `field_ptr` instructions, assumes they are all part of a struct
668 /// initialization expression, and emits compile errors for duplicate fields
669 /// as well as missing fields, if applicable.
670 /// This instruction asserts that there is at least one field_ptr instruction,
671 /// because it must use one of them to find out the struct type.
672 /// Uses the `pl_node` field. Payload is `Block`.
673 validate_struct_init_ptr,
674 /// A struct literal with a specified type, with no fields.
675 /// Uses the `un_node` field.
676 struct_init_empty,
677 /// Given a struct, union, enum, or opaque and a field name, returns the field type.
678 /// Uses the `pl_node` field. Payload is `FieldType`.
679 field_type,
680 /// Finalizes a typed struct initialization, performs validation, and returns the
681 /// struct value.
682 /// Uses the `pl_node` field. Payload is `StructInit`.
683 struct_init,
684 /// Converts an integer into an enum value.
685 /// Uses `pl_node` with payload `Bin`. `lhs` is enum type, `rhs` is operand.
686 int_to_enum,
687 /// Converts an enum value into an integer. Resulting type will be the tag type
688 /// of the enum. Uses `un_node`.
689 enum_to_int,
690 /// Implements the `@typeInfo` builtin. Uses `un_node`.
691 type_info,
692
693 /// Returns whether the instruction is one of the control flow "noreturn" types.
694 /// Function calls do not count.
695 pub fn isNoReturn(tag: Tag) bool {
696 return switch (tag) {
697 .add,
698 .addwrap,
699 .alloc,
700 .alloc_mut,
701 .alloc_inferred,
702 .alloc_inferred_mut,
703 .array_cat,
704 .array_mul,
705 .array_type,
706 .array_type_sentinel,
707 .indexable_ptr_len,
708 .as,
709 .as_node,
710 .@"asm",
711 .asm_volatile,
712 .bit_and,
713 .bitcast,
714 .bitcast_result_ptr,
715 .bit_or,
716 .block,
717 .block_inline,
718 .loop,
719 .bool_br_and,
720 .bool_br_or,
721 .bool_not,
722 .bool_and,
723 .bool_or,
724 .breakpoint,
725 .call,
726 .call_chkused,
727 .call_compile_time,
728 .call_none,
729 .call_none_chkused,
730 .cmp_lt,
731 .cmp_lte,
732 .cmp_eq,
733 .cmp_gte,
734 .cmp_gt,
735 .cmp_neq,
736 .coerce_result_ptr,
737 .struct_decl,
738 .struct_decl_packed,
739 .struct_decl_extern,
740 .union_decl,
741 .enum_decl,
742 .enum_decl_nonexhaustive,
743 .opaque_decl,
744 .dbg_stmt_node,
745 .decl_ref,
746 .decl_val,
747 .load,
748 .div,
749 .elem_ptr,
750 .elem_val,
751 .elem_ptr_node,
752 .elem_val_node,
753 .ensure_result_used,
754 .ensure_result_non_error,
755 .@"export",
756 .floatcast,
757 .field_ptr,
758 .field_val,
759 .field_ptr_named,
760 .field_val_named,
761 .fn_type,
762 .fn_type_var_args,
763 .fn_type_cc,
764 .fn_type_cc_var_args,
765 .has_decl,
766 .int,
767 .float,
768 .float128,
769 .intcast,
770 .int_type,
771 .is_non_null,
772 .is_null,
773 .is_non_null_ptr,
774 .is_null_ptr,
775 .is_err,
776 .is_err_ptr,
777 .mod_rem,
778 .mul,
779 .mulwrap,
780 .param_type,
781 .ptrtoint,
782 .ref,
783 .ret_ptr,
784 .ret_type,
785 .shl,
786 .shr,
787 .store,
788 .store_node,
789 .store_to_block_ptr,
790 .store_to_inferred_ptr,
791 .str,
792 .sub,
793 .subwrap,
794 .negate,
795 .negate_wrap,
796 .typeof,
797 .typeof_elem,
798 .xor,
799 .optional_type,
800 .optional_type_from_ptr_elem,
801 .optional_payload_safe,
802 .optional_payload_unsafe,
803 .optional_payload_safe_ptr,
804 .optional_payload_unsafe_ptr,
805 .err_union_payload_safe,
806 .err_union_payload_unsafe,
807 .err_union_payload_safe_ptr,
808 .err_union_payload_unsafe_ptr,
809 .err_union_code,
810 .err_union_code_ptr,
811 .error_to_int,
812 .int_to_error,
813 .ptr_type,
814 .ptr_type_simple,
815 .ensure_err_payload_void,
816 .enum_literal,
817 .enum_literal_small,
818 .merge_error_sets,
819 .error_union_type,
820 .bit_not,
821 .error_value,
822 .slice_start,
823 .slice_end,
824 .slice_sentinel,
825 .import,
826 .typeof_peer,
827 .resolve_inferred_alloc,
828 .set_eval_branch_quota,
829 .compile_log,
830 .elided,
831 .switch_capture,
832 .switch_capture_ref,
833 .switch_capture_multi,
834 .switch_capture_multi_ref,
835 .switch_capture_else,
836 .switch_capture_else_ref,
837 .switch_block,
838 .switch_block_multi,
839 .switch_block_else,
840 .switch_block_else_multi,
841 .switch_block_under,
842 .switch_block_under_multi,
843 .switch_block_ref,
844 .switch_block_ref_multi,
845 .switch_block_ref_else,
846 .switch_block_ref_else_multi,
847 .switch_block_ref_under,
848 .switch_block_ref_under_multi,
849 .validate_struct_init_ptr,
850 .struct_init_empty,
851 .struct_init,
852 .field_type,
853 .int_to_enum,
854 .enum_to_int,
855 .type_info,
856 => false,
857
858 .@"break",
859 .break_inline,
860 .condbr,
861 .condbr_inline,
862 .compile_error,
863 .ret_node,
864 .ret_tok,
865 .ret_coerce,
866 .@"unreachable",
867 .repeat,
868 .repeat_inline,
869 => true,
870 };
871 }
872 };
873
874 /// The position of a ZIR instruction within the `Code` instructions array.
875 pub const Index = u32;
876
877 /// A reference to a TypedValue, parameter of the current function,
878 /// or ZIR instruction.
879 ///
880 /// If the Ref has a tag in this enum, it refers to a TypedValue which may be
881 /// retrieved with Ref.toTypedValue().
882 ///
883 /// If the value of a Ref does not have a tag, it referes to either a parameter
884 /// of the current function or a ZIR instruction.
885 ///
886 /// The first values after the the last tag refer to parameters which may be
887 /// derived by subtracting typed_value_map.len.
888 ///
889 /// All further values refer to ZIR instructions which may be derived by
890 /// subtracting typed_value_map.len and the number of parameters.
891 ///
892 /// When adding a tag to this enum, consider adding a corresponding entry to
893 /// `simple_types` in astgen.
894 ///
895 /// The tag type is specified so that it is safe to bitcast between `[]u32`
896 /// and `[]Ref`.
897 pub const Ref = enum(u32) {
898 /// This Ref does not correspond to any ZIR instruction or constant
899 /// value and may instead be used as a sentinel to indicate null.
900 none,
901
902 u8_type,
903 i8_type,
904 u16_type,
905 i16_type,
906 u32_type,
907 i32_type,
908 u64_type,
909 i64_type,
910 usize_type,
911 isize_type,
912 c_short_type,
913 c_ushort_type,
914 c_int_type,
915 c_uint_type,
916 c_long_type,
917 c_ulong_type,
918 c_longlong_type,
919 c_ulonglong_type,
920 c_longdouble_type,
921 f16_type,
922 f32_type,
923 f64_type,
924 f128_type,
925 c_void_type,
926 bool_type,
927 void_type,
928 type_type,
929 anyerror_type,
930 comptime_int_type,
931 comptime_float_type,
932 noreturn_type,
933 null_type,
934 undefined_type,
935 fn_noreturn_no_args_type,
936 fn_void_no_args_type,
937 fn_naked_noreturn_no_args_type,
938 fn_ccc_void_no_args_type,
939 single_const_pointer_to_comptime_int_type,
940 const_slice_u8_type,
941 enum_literal_type,
942
943 /// `undefined` (untyped)
944 undef,
945 /// `0` (comptime_int)
946 zero,
947 /// `1` (comptime_int)
948 one,
949 /// `{}`
950 void_value,
951 /// `unreachable` (noreturn type)
952 unreachable_value,
953 /// `null` (untyped)
954 null_value,
955 /// `true`
956 bool_true,
957 /// `false`
958 bool_false,
959 /// `.{}` (untyped)
960 empty_struct,
961 /// `0` (usize)
962 zero_usize,
963 /// `1` (usize)
964 one_usize,
965
966 _,
967
968 pub const typed_value_map = std.enums.directEnumArray(Ref, TypedValue, 0, .{
969 .none = undefined,
970
971 .u8_type = .{
972 .ty = Type.initTag(.type),
973 .val = Value.initTag(.u8_type),
974 },
975 .i8_type = .{
976 .ty = Type.initTag(.type),
977 .val = Value.initTag(.i8_type),
978 },
979 .u16_type = .{
980 .ty = Type.initTag(.type),
981 .val = Value.initTag(.u16_type),
982 },
983 .i16_type = .{
984 .ty = Type.initTag(.type),
985 .val = Value.initTag(.i16_type),
986 },
987 .u32_type = .{
988 .ty = Type.initTag(.type),
989 .val = Value.initTag(.u32_type),
990 },
991 .i32_type = .{
992 .ty = Type.initTag(.type),
993 .val = Value.initTag(.i32_type),
994 },
995 .u64_type = .{
996 .ty = Type.initTag(.type),
997 .val = Value.initTag(.u64_type),
998 },
999 .i64_type = .{
1000 .ty = Type.initTag(.type),
1001 .val = Value.initTag(.i64_type),
1002 },
1003 .usize_type = .{
1004 .ty = Type.initTag(.type),
1005 .val = Value.initTag(.usize_type),
1006 },
1007 .isize_type = .{
1008 .ty = Type.initTag(.type),
1009 .val = Value.initTag(.isize_type),
1010 },
1011 .c_short_type = .{
1012 .ty = Type.initTag(.type),
1013 .val = Value.initTag(.c_short_type),
1014 },
1015 .c_ushort_type = .{
1016 .ty = Type.initTag(.type),
1017 .val = Value.initTag(.c_ushort_type),
1018 },
1019 .c_int_type = .{
1020 .ty = Type.initTag(.type),
1021 .val = Value.initTag(.c_int_type),
1022 },
1023 .c_uint_type = .{
1024 .ty = Type.initTag(.type),
1025 .val = Value.initTag(.c_uint_type),
1026 },
1027 .c_long_type = .{
1028 .ty = Type.initTag(.type),
1029 .val = Value.initTag(.c_long_type),
1030 },
1031 .c_ulong_type = .{
1032 .ty = Type.initTag(.type),
1033 .val = Value.initTag(.c_ulong_type),
1034 },
1035 .c_longlong_type = .{
1036 .ty = Type.initTag(.type),
1037 .val = Value.initTag(.c_longlong_type),
1038 },
1039 .c_ulonglong_type = .{
1040 .ty = Type.initTag(.type),
1041 .val = Value.initTag(.c_ulonglong_type),
1042 },
1043 .c_longdouble_type = .{
1044 .ty = Type.initTag(.type),
1045 .val = Value.initTag(.c_longdouble_type),
1046 },
1047 .f16_type = .{
1048 .ty = Type.initTag(.type),
1049 .val = Value.initTag(.f16_type),
1050 },
1051 .f32_type = .{
1052 .ty = Type.initTag(.type),
1053 .val = Value.initTag(.f32_type),
1054 },
1055 .f64_type = .{
1056 .ty = Type.initTag(.type),
1057 .val = Value.initTag(.f64_type),
1058 },
1059 .f128_type = .{
1060 .ty = Type.initTag(.type),
1061 .val = Value.initTag(.f128_type),
1062 },
1063 .c_void_type = .{
1064 .ty = Type.initTag(.type),
1065 .val = Value.initTag(.c_void_type),
1066 },
1067 .bool_type = .{
1068 .ty = Type.initTag(.type),
1069 .val = Value.initTag(.bool_type),
1070 },
1071 .void_type = .{
1072 .ty = Type.initTag(.type),
1073 .val = Value.initTag(.void_type),
1074 },
1075 .type_type = .{
1076 .ty = Type.initTag(.type),
1077 .val = Value.initTag(.type_type),
1078 },
1079 .anyerror_type = .{
1080 .ty = Type.initTag(.type),
1081 .val = Value.initTag(.anyerror_type),
1082 },
1083 .comptime_int_type = .{
1084 .ty = Type.initTag(.type),
1085 .val = Value.initTag(.comptime_int_type),
1086 },
1087 .comptime_float_type = .{
1088 .ty = Type.initTag(.type),
1089 .val = Value.initTag(.comptime_float_type),
1090 },
1091 .noreturn_type = .{
1092 .ty = Type.initTag(.type),
1093 .val = Value.initTag(.noreturn_type),
1094 },
1095 .null_type = .{
1096 .ty = Type.initTag(.type),
1097 .val = Value.initTag(.null_type),
1098 },
1099 .undefined_type = .{
1100 .ty = Type.initTag(.type),
1101 .val = Value.initTag(.undefined_type),
1102 },
1103 .fn_noreturn_no_args_type = .{
1104 .ty = Type.initTag(.type),
1105 .val = Value.initTag(.fn_noreturn_no_args_type),
1106 },
1107 .fn_void_no_args_type = .{
1108 .ty = Type.initTag(.type),
1109 .val = Value.initTag(.fn_void_no_args_type),
1110 },
1111 .fn_naked_noreturn_no_args_type = .{
1112 .ty = Type.initTag(.type),
1113 .val = Value.initTag(.fn_naked_noreturn_no_args_type),
1114 },
1115 .fn_ccc_void_no_args_type = .{
1116 .ty = Type.initTag(.type),
1117 .val = Value.initTag(.fn_ccc_void_no_args_type),
1118 },
1119 .single_const_pointer_to_comptime_int_type = .{
1120 .ty = Type.initTag(.type),
1121 .val = Value.initTag(.single_const_pointer_to_comptime_int_type),
1122 },
1123 .const_slice_u8_type = .{
1124 .ty = Type.initTag(.type),
1125 .val = Value.initTag(.const_slice_u8_type),
1126 },
1127 .enum_literal_type = .{
1128 .ty = Type.initTag(.type),
1129 .val = Value.initTag(.enum_literal_type),
1130 },
1131
1132 .undef = .{
1133 .ty = Type.initTag(.@"undefined"),
1134 .val = Value.initTag(.undef),
1135 },
1136 .zero = .{
1137 .ty = Type.initTag(.comptime_int),
1138 .val = Value.initTag(.zero),
1139 },
1140 .zero_usize = .{
1141 .ty = Type.initTag(.usize),
1142 .val = Value.initTag(.zero),
1143 },
1144 .one = .{
1145 .ty = Type.initTag(.comptime_int),
1146 .val = Value.initTag(.one),
1147 },
1148 .one_usize = .{
1149 .ty = Type.initTag(.usize),
1150 .val = Value.initTag(.one),
1151 },
1152 .void_value = .{
1153 .ty = Type.initTag(.void),
1154 .val = Value.initTag(.void_value),
1155 },
1156 .unreachable_value = .{
1157 .ty = Type.initTag(.noreturn),
1158 .val = Value.initTag(.unreachable_value),
1159 },
1160 .null_value = .{
1161 .ty = Type.initTag(.@"null"),
1162 .val = Value.initTag(.null_value),
1163 },
1164 .bool_true = .{
1165 .ty = Type.initTag(.bool),
1166 .val = Value.initTag(.bool_true),
1167 },
1168 .bool_false = .{
1169 .ty = Type.initTag(.bool),
1170 .val = Value.initTag(.bool_false),
1171 },
1172 .empty_struct = .{
1173 .ty = Type.initTag(.empty_struct_literal),
1174 .val = Value.initTag(.empty_struct_value),
1175 },
1176 });
1177 };
1178
1179 /// All instructions have an 8-byte payload, which is contained within
1180 /// this union. `Tag` determines which union field is active, as well as
1181 /// how to interpret the data within.
1182 pub const Data = union {
1183 /// Used for unary operators, with an AST node source location.
1184 un_node: struct {
1185 /// Offset from Decl AST node index.
1186 src_node: i32,
1187 /// The meaning of this operand depends on the corresponding `Tag`.
1188 operand: Ref,
1189
1190 pub fn src(self: @This()) LazySrcLoc {
1191 return .{ .node_offset = self.src_node };
1192 }
1193 },
1194 /// Used for unary operators, with a token source location.
1195 un_tok: struct {
1196 /// Offset from Decl AST token index.
1197 src_tok: ast.TokenIndex,
1198 /// The meaning of this operand depends on the corresponding `Tag`.
1199 operand: Ref,
1200
1201 pub fn src(self: @This()) LazySrcLoc {
1202 return .{ .token_offset = self.src_tok };
1203 }
1204 },
1205 pl_node: struct {
1206 /// Offset from Decl AST node index.
1207 /// `Tag` determines which kind of AST node this points to.
1208 src_node: i32,
1209 /// index into extra.
1210 /// `Tag` determines what lives there.
1211 payload_index: u32,
1212
1213 pub fn src(self: @This()) LazySrcLoc {
1214 return .{ .node_offset = self.src_node };
1215 }
1216 },
1217 bin: Bin,
1218 /// For strings which may contain null bytes.
1219 str: struct {
1220 /// Offset into `string_bytes`.
1221 start: u32,
1222 /// Number of bytes in the string.
1223 len: u32,
1224
1225 pub fn get(self: @This(), code: Code) []const u8 {
1226 return code.string_bytes[self.start..][0..self.len];
1227 }
1228 },
1229 /// Strings 8 or fewer bytes which may not contain null bytes.
1230 small_str: struct {
1231 bytes: [8]u8,
1232
1233 pub fn get(self: @This()) []const u8 {
1234 const end = for (self.bytes) |byte, i| {
1235 if (byte == 0) break i;
1236 } else self.bytes.len;
1237 return self.bytes[0..end];
1238 }
1239 },
1240 str_tok: struct {
1241 /// Offset into `string_bytes`. Null-terminated.
1242 start: u32,
1243 /// Offset from Decl AST token index.
1244 src_tok: u32,
1245
1246 pub fn get(self: @This(), code: Code) [:0]const u8 {
1247 return code.nullTerminatedString(self.start);
1248 }
1249
1250 pub fn src(self: @This()) LazySrcLoc {
1251 return .{ .token_offset = self.src_tok };
1252 }
1253 },
1254 /// Offset from Decl AST token index.
1255 tok: ast.TokenIndex,
1256 /// Offset from Decl AST node index.
1257 node: i32,
1258 int: u64,
1259 float: struct {
1260 /// Offset from Decl AST node index.
1261 /// `Tag` determines which kind of AST node this points to.
1262 src_node: i32,
1263 number: f32,
1264
1265 pub fn src(self: @This()) LazySrcLoc {
1266 return .{ .node_offset = self.src_node };
1267 }
1268 },
1269 array_type_sentinel: struct {
1270 len: Ref,
1271 /// index into extra, points to an `ArrayTypeSentinel`
1272 payload_index: u32,
1273 },
1274 ptr_type_simple: struct {
1275 is_allowzero: bool,
1276 is_mutable: bool,
1277 is_volatile: bool,
1278 size: std.builtin.TypeInfo.Pointer.Size,
1279 elem_type: Ref,
1280 },
1281 ptr_type: struct {
1282 flags: packed struct {
1283 is_allowzero: bool,
1284 is_mutable: bool,
1285 is_volatile: bool,
1286 has_sentinel: bool,
1287 has_align: bool,
1288 has_bit_range: bool,
1289 _: u2 = undefined,
1290 },
1291 size: std.builtin.TypeInfo.Pointer.Size,
1292 /// Index into extra. See `PtrType`.
1293 payload_index: u32,
1294 },
1295 int_type: struct {
1296 /// Offset from Decl AST node index.
1297 /// `Tag` determines which kind of AST node this points to.
1298 src_node: i32,
1299 signedness: std.builtin.Signedness,
1300 bit_count: u16,
1301
1302 pub fn src(self: @This()) LazySrcLoc {
1303 return .{ .node_offset = self.src_node };
1304 }
1305 },
1306 bool_br: struct {
1307 lhs: Ref,
1308 /// Points to a `Block`.
1309 payload_index: u32,
1310 },
1311 param_type: struct {
1312 callee: Ref,
1313 param_index: u32,
1314 },
1315 @"unreachable": struct {
1316 /// Offset from Decl AST node index.
1317 /// `Tag` determines which kind of AST node this points to.
1318 src_node: i32,
1319 /// `false`: Not safety checked - the compiler will assume the
1320 /// correctness of this instruction.
1321 /// `true`: In safety-checked modes, this will generate a call
1322 /// to the panic function unless it can be proven unreachable by the compiler.
1323 safety: bool,
1324
1325 pub fn src(self: @This()) LazySrcLoc {
1326 return .{ .node_offset = self.src_node };
1327 }
1328 },
1329 @"break": struct {
1330 block_inst: Index,
1331 operand: Ref,
1332 },
1333 switch_capture: struct {
1334 switch_inst: Index,
1335 prong_index: u32,
1336 },
1337
1338 // Make sure we don't accidentally add a field to make this union
1339 // bigger than expected. Note that in Debug builds, Zig is allowed
1340 // to insert a secret field for safety checks.
1341 comptime {
1342 if (std.builtin.mode != .Debug) {
1343 assert(@sizeOf(Data) == 8);
1344 }
1345 }
1346 };
1347
1348 /// Stored in extra. Trailing is:
1349 /// * output_name: u32 // index into string_bytes (null terminated) if output is present
1350 /// * arg: Ref // for every args_len.
1351 /// * constraint: u32 // index into string_bytes (null terminated) for every args_len.
1352 /// * clobber: u32 // index into string_bytes (null terminated) for every clobbers_len.
1353 pub const Asm = struct {
1354 asm_source: Ref,
1355 return_type: Ref,
1356 /// May be omitted.
1357 output: Ref,
1358 args_len: u32,
1359 clobbers_len: u32,
1360 };
1361
1362 /// This data is stored inside extra, with trailing parameter type indexes
1363 /// according to `param_types_len`.
1364 /// Each param type is a `Ref`.
1365 pub const FnTypeCc = struct {
1366 return_type: Ref,
1367 cc: Ref,
1368 param_types_len: u32,
1369 };
1370
1371 /// This data is stored inside extra, with trailing parameter type indexes
1372 /// according to `param_types_len`.
1373 /// Each param type is a `Ref`.
1374 pub const FnType = struct {
1375 return_type: Ref,
1376 param_types_len: u32,
1377 };
1378
1379 /// This data is stored inside extra, with trailing operands according to `operands_len`.
1380 /// Each operand is a `Ref`.
1381 pub const MultiOp = struct {
1382 operands_len: u32,
1383 };
1384
1385 /// This data is stored inside extra, with trailing operands according to `body_len`.
1386 /// Each operand is an `Index`.
1387 pub const Block = struct {
1388 body_len: u32,
1389 };
1390
1391 /// Stored inside extra, with trailing arguments according to `args_len`.
1392 /// Each argument is a `Ref`.
1393 pub const Call = struct {
1394 callee: Ref,
1395 args_len: u32,
1396 };
1397
1398 /// This data is stored inside extra, with two sets of trailing `Ref`:
1399 /// * 0. the then body, according to `then_body_len`.
1400 /// * 1. the else body, according to `else_body_len`.
1401 pub const CondBr = struct {
1402 condition: Ref,
1403 then_body_len: u32,
1404 else_body_len: u32,
1405 };
1406
1407 /// Stored in extra. Depending on the flags in Data, there will be up to 4
1408 /// trailing Ref fields:
1409 /// 0. sentinel: Ref // if `has_sentinel` flag is set
1410 /// 1. align: Ref // if `has_align` flag is set
1411 /// 2. bit_start: Ref // if `has_bit_range` flag is set
1412 /// 3. bit_end: Ref // if `has_bit_range` flag is set
1413 pub const PtrType = struct {
1414 elem_type: Ref,
1415 };
1416
1417 pub const ArrayTypeSentinel = struct {
1418 sentinel: Ref,
1419 elem_type: Ref,
1420 };
1421
1422 pub const SliceStart = struct {
1423 lhs: Ref,
1424 start: Ref,
1425 };
1426
1427 pub const SliceEnd = struct {
1428 lhs: Ref,
1429 start: Ref,
1430 end: Ref,
1431 };
1432
1433 pub const SliceSentinel = struct {
1434 lhs: Ref,
1435 start: Ref,
1436 end: Ref,
1437 sentinel: Ref,
1438 };
1439
1440 /// The meaning of these operands depends on the corresponding `Tag`.
1441 pub const Bin = struct {
1442 lhs: Ref,
1443 rhs: Ref,
1444 };
1445
1446 /// This form is supported when there are no ranges, and exactly 1 item per block.
1447 /// Depending on zir tag and len fields, extra fields trail
1448 /// this one in the extra array.
1449 /// 0. else_body { // If the tag has "_else" or "_under" in it.
1450 /// body_len: u32,
1451 /// body member Index for every body_len
1452 /// }
1453 /// 1. cases: {
1454 /// item: Ref,
1455 /// body_len: u32,
1456 /// body member Index for every body_len
1457 /// } for every cases_len
1458 pub const SwitchBlock = struct {
1459 operand: Ref,
1460 cases_len: u32,
1461 };
1462
1463 /// This form is required when there exists a block which has more than one item,
1464 /// or a range.
1465 /// Depending on zir tag and len fields, extra fields trail
1466 /// this one in the extra array.
1467 /// 0. else_body { // If the tag has "_else" or "_under" in it.
1468 /// body_len: u32,
1469 /// body member Index for every body_len
1470 /// }
1471 /// 1. scalar_cases: { // for every scalar_cases_len
1472 /// item: Ref,
1473 /// body_len: u32,
1474 /// body member Index for every body_len
1475 /// }
1476 /// 2. multi_cases: { // for every multi_cases_len
1477 /// items_len: u32,
1478 /// ranges_len: u32,
1479 /// body_len: u32,
1480 /// item: Ref // for every items_len
1481 /// ranges: { // for every ranges_len
1482 /// item_first: Ref,
1483 /// item_last: Ref,
1484 /// }
1485 /// body member Index for every body_len
1486 /// }
1487 pub const SwitchBlockMulti = struct {
1488 operand: Ref,
1489 scalar_cases_len: u32,
1490 multi_cases_len: u32,
1491 };
1492
1493 pub const Field = struct {
1494 lhs: Ref,
1495 /// Offset into `string_bytes`.
1496 field_name_start: u32,
1497 };
1498
1499 pub const FieldNamed = struct {
1500 lhs: Ref,
1501 field_name: Ref,
1502 };
1503
1504 pub const As = struct {
1505 dest_type: Ref,
1506 operand: Ref,
1507 };
1508
1509 /// Trailing:
1510 /// 0. has_bits: u32 // for every 16 fields
1511 /// - sets of 2 bits:
1512 /// 0b0X: whether corresponding field has an align expression
1513 /// 0bX0: whether corresponding field has a default expression
1514 /// 1. fields: { // for every fields_len
1515 /// field_name: u32,
1516 /// field_type: Ref,
1517 /// align: Ref, // if corresponding bit is set
1518 /// default_value: Ref, // if corresponding bit is set
1519 /// }
1520 pub const StructDecl = struct {
1521 fields_len: u32,
1522 };
1523
1524 /// Trailing:
1525 /// 0. has_bits: u32 // for every 32 fields
1526 /// - the bit is whether corresponding field has an value expression
1527 /// 1. field_name: u32 // for every field: null terminated string index
1528 /// 2. value: Ref // for every field for which corresponding bit is set
1529 pub const EnumDecl = struct {
1530 /// Can be `Ref.none`.
1531 tag_type: Ref,
1532 fields_len: u32,
1533 };
1534
1535 /// Trailing:
1536 /// 0. has_bits: u32 // for every 10 fields (+1)
1537 /// - first bit is special: set if and only if auto enum tag is enabled.
1538 /// - sets of 3 bits:
1539 /// 0b00X: whether corresponding field has a type expression
1540 /// 0b0X0: whether corresponding field has a align expression
1541 /// 0bX00: whether corresponding field has a tag value expression
1542 /// 1. field_name: u32 // for every field: null terminated string index
1543 /// 2. opt_exprs // Ref for every field for which corresponding bit is set
1544 /// - interleaved. type if present, align if present, tag value if present.
1545 pub const UnionDecl = struct {
1546 /// Can be `Ref.none`.
1547 tag_type: Ref,
1548 fields_len: u32,
1549 };
1550
1551 /// A f128 value, broken up into 4 u32 parts.
1552 pub const Float128 = struct {
1553 piece0: u32,
1554 piece1: u32,
1555 piece2: u32,
1556 piece3: u32,
1557
1558 pub fn get(self: Float128) f128 {
1559 const int_bits = @as(u128, self.piece0) |
1560 (@as(u128, self.piece1) << 32) |
1561 (@as(u128, self.piece2) << 64) |
1562 (@as(u128, self.piece3) << 96);
1563 return @bitCast(f128, int_bits);
1564 }
1565 };
1566
1567 /// Trailing is an item per field.
1568 pub const StructInit = struct {
1569 fields_len: u32,
1570
1571 pub const Item = struct {
1572 /// The `field_type` ZIR instruction for this field init.
1573 field_type: Index,
1574 /// The field init expression to be used as the field value.
1575 init: Ref,
1576 };
1577 };
1578
1579 pub const FieldType = struct {
1580 container_type: Ref,
1581 /// Offset into `string_bytes`, null terminated.
1582 name_start: u32,
1583 };
1584};
1585
1586pub const SpecialProng = enum { none, @"else", under };
1587
1588const Writer = struct {
1589 gpa: *Allocator,
1590 arena: *Allocator,
1591 scope: *Module.Scope,
1592 code: Code,
1593 indent: usize,
1594 param_count: usize,
1595
1596 fn writeInstToStream(
1597 self: *Writer,
1598 stream: anytype,
1599 inst: Inst.Index,
1600 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1601 const tags = self.code.instructions.items(.tag);
1602 const tag = tags[inst];
1603 try stream.print("= {s}(", .{@tagName(tags[inst])});
1604 switch (tag) {
1605 .array_type,
1606 .as,
1607 .coerce_result_ptr,
1608 .elem_ptr,
1609 .elem_val,
1610 .intcast,
1611 .store,
1612 .store_to_block_ptr,
1613 .store_to_inferred_ptr,
1614 => try self.writeBin(stream, inst),
1615
1616 .alloc,
1617 .alloc_mut,
1618 .indexable_ptr_len,
1619 .bit_not,
1620 .bool_not,
1621 .negate,
1622 .negate_wrap,
1623 .call_none,
1624 .call_none_chkused,
1625 .compile_error,
1626 .load,
1627 .ensure_result_used,
1628 .ensure_result_non_error,
1629 .import,
1630 .ptrtoint,
1631 .ret_node,
1632 .set_eval_branch_quota,
1633 .resolve_inferred_alloc,
1634 .optional_type,
1635 .optional_type_from_ptr_elem,
1636 .optional_payload_safe,
1637 .optional_payload_unsafe,
1638 .optional_payload_safe_ptr,
1639 .optional_payload_unsafe_ptr,
1640 .err_union_payload_safe,
1641 .err_union_payload_unsafe,
1642 .err_union_payload_safe_ptr,
1643 .err_union_payload_unsafe_ptr,
1644 .err_union_code,
1645 .err_union_code_ptr,
1646 .int_to_error,
1647 .error_to_int,
1648 .is_non_null,
1649 .is_null,
1650 .is_non_null_ptr,
1651 .is_null_ptr,
1652 .is_err,
1653 .is_err_ptr,
1654 .typeof,
1655 .typeof_elem,
1656 .struct_init_empty,
1657 .enum_to_int,
1658 .type_info,
1659 => try self.writeUnNode(stream, inst),
1660
1661 .ref,
1662 .ret_tok,
1663 .ret_coerce,
1664 .ensure_err_payload_void,
1665 => try self.writeUnTok(stream, inst),
1666
1667 .bool_br_and,
1668 .bool_br_or,
1669 => try self.writeBoolBr(stream, inst),
1670
1671 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
1672 .param_type => try self.writeParamType(stream, inst),
1673 .ptr_type_simple => try self.writePtrTypeSimple(stream, inst),
1674 .ptr_type => try self.writePtrType(stream, inst),
1675 .int => try self.writeInt(stream, inst),
1676 .float => try self.writeFloat(stream, inst),
1677 .float128 => try self.writeFloat128(stream, inst),
1678 .str => try self.writeStr(stream, inst),
1679 .elided => try stream.writeAll(")"),
1680 .int_type => try self.writeIntType(stream, inst),
1681
1682 .@"break",
1683 .break_inline,
1684 => try self.writeBreak(stream, inst),
1685
1686 .@"asm",
1687 .asm_volatile,
1688 .elem_ptr_node,
1689 .elem_val_node,
1690 .field_ptr_named,
1691 .field_val_named,
1692 .floatcast,
1693 .slice_start,
1694 .slice_end,
1695 .slice_sentinel,
1696 .union_decl,
1697 .enum_decl,
1698 .enum_decl_nonexhaustive,
1699 .struct_init,
1700 .field_type,
1701 => try self.writePlNode(stream, inst),
1702
1703 .add,
1704 .addwrap,
1705 .array_cat,
1706 .array_mul,
1707 .mul,
1708 .mulwrap,
1709 .sub,
1710 .subwrap,
1711 .bool_and,
1712 .bool_or,
1713 .cmp_lt,
1714 .cmp_lte,
1715 .cmp_eq,
1716 .cmp_gte,
1717 .cmp_gt,
1718 .cmp_neq,
1719 .div,
1720 .has_decl,
1721 .mod_rem,
1722 .shl,
1723 .shr,
1724 .xor,
1725 .store_node,
1726 .error_union_type,
1727 .@"export",
1728 .merge_error_sets,
1729 .bit_and,
1730 .bit_or,
1731 .int_to_enum,
1732 => try self.writePlNodeBin(stream, inst),
1733
1734 .call,
1735 .call_chkused,
1736 .call_compile_time,
1737 => try self.writePlNodeCall(stream, inst),
1738
1739 .block,
1740 .block_inline,
1741 .loop,
1742 .validate_struct_init_ptr,
1743 => try self.writePlNodeBlock(stream, inst),
1744
1745 .condbr,
1746 .condbr_inline,
1747 => try self.writePlNodeCondBr(stream, inst),
1748
1749 .struct_decl,
1750 .struct_decl_packed,
1751 .struct_decl_extern,
1752 => try self.writeStructDecl(stream, inst),
1753
1754 .switch_block => try self.writePlNodeSwitchBr(stream, inst, .none),
1755 .switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),
1756 .switch_block_under => try self.writePlNodeSwitchBr(stream, inst, .under),
1757 .switch_block_ref => try self.writePlNodeSwitchBr(stream, inst, .none),
1758 .switch_block_ref_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),
1759 .switch_block_ref_under => try self.writePlNodeSwitchBr(stream, inst, .under),
1760
1761 .switch_block_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .none),
1762 .switch_block_else_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .@"else"),
1763 .switch_block_under_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .under),
1764 .switch_block_ref_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .none),
1765 .switch_block_ref_else_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .@"else"),
1766 .switch_block_ref_under_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .under),
1767
1768 .compile_log,
1769 .typeof_peer,
1770 => try self.writePlNodeMultiOp(stream, inst),
1771
1772 .decl_ref,
1773 .decl_val,
1774 => try self.writePlNodeDecl(stream, inst),
1775
1776 .field_ptr,
1777 .field_val,
1778 => try self.writePlNodeField(stream, inst),
1779
1780 .as_node => try self.writeAs(stream, inst),
1781
1782 .breakpoint,
1783 .opaque_decl,
1784 .dbg_stmt_node,
1785 .ret_ptr,
1786 .ret_type,
1787 .repeat,
1788 .repeat_inline,
1789 .alloc_inferred,
1790 .alloc_inferred_mut,
1791 => try self.writeNode(stream, inst),
1792
1793 .error_value,
1794 .enum_literal,
1795 => try self.writeStrTok(stream, inst),
1796
1797 .fn_type => try self.writeFnType(stream, inst, false),
1798 .fn_type_cc => try self.writeFnTypeCc(stream, inst, false),
1799 .fn_type_var_args => try self.writeFnType(stream, inst, true),
1800 .fn_type_cc_var_args => try self.writeFnTypeCc(stream, inst, true),
1801
1802 .@"unreachable" => try self.writeUnreachable(stream, inst),
1803
1804 .enum_literal_small => try self.writeSmallStr(stream, inst),
1805
1806 .switch_capture,
1807 .switch_capture_ref,
1808 .switch_capture_multi,
1809 .switch_capture_multi_ref,
1810 .switch_capture_else,
1811 .switch_capture_else_ref,
1812 => try self.writeSwitchCapture(stream, inst),
1813
1814 .bitcast,
1815 .bitcast_result_ptr,
1816 => try stream.writeAll("TODO)"),
1817 }
1818 }
1819
1820 fn writeBin(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1821 const inst_data = self.code.instructions.items(.data)[inst].bin;
1822 try self.writeInstRef(stream, inst_data.lhs);
1823 try stream.writeAll(", ");
1824 try self.writeInstRef(stream, inst_data.rhs);
1825 try stream.writeByte(')');
1826 }
1827
1828 fn writeUnNode(
1829 self: *Writer,
1830 stream: anytype,
1831 inst: Inst.Index,
1832 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1833 const inst_data = self.code.instructions.items(.data)[inst].un_node;
1834 try self.writeInstRef(stream, inst_data.operand);
1835 try stream.writeAll(") ");
1836 try self.writeSrc(stream, inst_data.src());
1837 }
1838
1839 fn writeUnTok(
1840 self: *Writer,
1841 stream: anytype,
1842 inst: Inst.Index,
1843 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1844 const inst_data = self.code.instructions.items(.data)[inst].un_tok;
1845 try self.writeInstRef(stream, inst_data.operand);
1846 try stream.writeAll(") ");
1847 try self.writeSrc(stream, inst_data.src());
1848 }
1849
1850 fn writeArrayTypeSentinel(
1851 self: *Writer,
1852 stream: anytype,
1853 inst: Inst.Index,
1854 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1855 const inst_data = self.code.instructions.items(.data)[inst].array_type_sentinel;
1856 try stream.writeAll("TODO)");
1857 }
1858
1859 fn writeParamType(
1860 self: *Writer,
1861 stream: anytype,
1862 inst: Inst.Index,
1863 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1864 const inst_data = self.code.instructions.items(.data)[inst].param_type;
1865 try self.writeInstRef(stream, inst_data.callee);
1866 try stream.print(", {d})", .{inst_data.param_index});
1867 }
1868
1869 fn writePtrTypeSimple(
1870 self: *Writer,
1871 stream: anytype,
1872 inst: Inst.Index,
1873 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1874 const inst_data = self.code.instructions.items(.data)[inst].ptr_type_simple;
1875 try stream.writeAll("TODO)");
1876 }
1877
1878 fn writePtrType(
1879 self: *Writer,
1880 stream: anytype,
1881 inst: Inst.Index,
1882 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1883 const inst_data = self.code.instructions.items(.data)[inst].ptr_type;
1884 try stream.writeAll("TODO)");
1885 }
1886
1887 fn writeInt(
1888 self: *Writer,
1889 stream: anytype,
1890 inst: Inst.Index,
1891 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1892 const inst_data = self.code.instructions.items(.data)[inst].int;
1893 try stream.print("{d})", .{inst_data});
1894 }
1895
1896 fn writeFloat(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1897 const inst_data = self.code.instructions.items(.data)[inst].float;
1898 const src = inst_data.src();
1899 try stream.print("{d}) ", .{inst_data.number});
1900 try self.writeSrc(stream, src);
1901 }
1902
1903 fn writeFloat128(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1904 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1905 const extra = self.code.extraData(Inst.Float128, inst_data.payload_index).data;
1906 const src = inst_data.src();
1907 const number = extra.get();
1908 // TODO improve std.format to be able to print f128 values
1909 try stream.print("{d}) ", .{@floatCast(f64, number)});
1910 try self.writeSrc(stream, src);
1911 }
1912
1913 fn writeStr(
1914 self: *Writer,
1915 stream: anytype,
1916 inst: Inst.Index,
1917 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1918 const inst_data = self.code.instructions.items(.data)[inst].str;
1919 const str = inst_data.get(self.code);
1920 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});
1921 }
1922
1923 fn writePlNode(
1924 self: *Writer,
1925 stream: anytype,
1926 inst: Inst.Index,
1927 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1928 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1929 try stream.writeAll("TODO) ");
1930 try self.writeSrc(stream, inst_data.src());
1931 }
1932
1933 fn writePlNodeBin(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1934 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1935 const extra = self.code.extraData(Inst.Bin, inst_data.payload_index).data;
1936 try self.writeInstRef(stream, extra.lhs);
1937 try stream.writeAll(", ");
1938 try self.writeInstRef(stream, extra.rhs);
1939 try stream.writeAll(") ");
1940 try self.writeSrc(stream, inst_data.src());
1941 }
1942
1943 fn writePlNodeCall(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1944 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1945 const extra = self.code.extraData(Inst.Call, inst_data.payload_index);
1946 const args = self.code.refSlice(extra.end, extra.data.args_len);
1947
1948 try self.writeInstRef(stream, extra.data.callee);
1949 try stream.writeAll(", [");
1950 for (args) |arg, i| {
1951 if (i != 0) try stream.writeAll(", ");
1952 try self.writeInstRef(stream, arg);
1953 }
1954 try stream.writeAll("]) ");
1955 try self.writeSrc(stream, inst_data.src());
1956 }
1957
1958 fn writePlNodeBlock(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1959 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1960 const extra = self.code.extraData(Inst.Block, inst_data.payload_index);
1961 const body = self.code.extra[extra.end..][0..extra.data.body_len];
1962 try stream.writeAll("{\n");
1963 self.indent += 2;
1964 try self.writeBody(stream, body);
1965 self.indent -= 2;
1966 try stream.writeByteNTimes(' ', self.indent);
1967 try stream.writeAll("}) ");
1968 try self.writeSrc(stream, inst_data.src());
1969 }
1970
1971 fn writePlNodeCondBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1972 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1973 const extra = self.code.extraData(Inst.CondBr, inst_data.payload_index);
1974 const then_body = self.code.extra[extra.end..][0..extra.data.then_body_len];
1975 const else_body = self.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
1976 try self.writeInstRef(stream, extra.data.condition);
1977 try stream.writeAll(", {\n");
1978 self.indent += 2;
1979 try self.writeBody(stream, then_body);
1980 self.indent -= 2;
1981 try stream.writeByteNTimes(' ', self.indent);
1982 try stream.writeAll("}, {\n");
1983 self.indent += 2;
1984 try self.writeBody(stream, else_body);
1985 self.indent -= 2;
1986 try stream.writeByteNTimes(' ', self.indent);
1987 try stream.writeAll("}) ");
1988 try self.writeSrc(stream, inst_data.src());
1989 }
1990
1991 fn writeStructDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1992 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1993 const extra = self.code.extraData(Inst.StructDecl, inst_data.payload_index);
1994 const fields_len = extra.data.fields_len;
1995 const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable;
1996
1997 try stream.writeAll("{\n");
1998 self.indent += 2;
1999
2000 var field_index: usize = extra.end + bit_bags_count;
2001 var bit_bag_index: usize = extra.end;
2002 var cur_bit_bag: u32 = undefined;
2003 var field_i: u32 = 0;
2004 while (field_i < fields_len) : (field_i += 1) {
2005 if (field_i % 16 == 0) {
2006 cur_bit_bag = self.code.extra[bit_bag_index];
2007 bit_bag_index += 1;
2008 }
2009 const has_align = @truncate(u1, cur_bit_bag) != 0;
2010 cur_bit_bag >>= 1;
2011 const has_default = @truncate(u1, cur_bit_bag) != 0;
2012 cur_bit_bag >>= 1;
2013
2014 const field_name = self.code.nullTerminatedString(self.code.extra[field_index]);
2015 field_index += 1;
2016 const field_type = @intToEnum(Inst.Ref, self.code.extra[field_index]);
2017 field_index += 1;
2018
2019 try stream.writeByteNTimes(' ', self.indent);
2020 try stream.print("{}: ", .{std.zig.fmtId(field_name)});
2021 try self.writeInstRef(stream, field_type);
2022
2023 if (has_align) {
2024 const align_ref = @intToEnum(Inst.Ref, self.code.extra[field_index]);
2025 field_index += 1;
2026
2027 try stream.writeAll(" align(");
2028 try self.writeInstRef(stream, align_ref);
2029 try stream.writeAll(")");
2030 }
2031 if (has_default) {
2032 const default_ref = @intToEnum(Inst.Ref, self.code.extra[field_index]);
2033 field_index += 1;
2034
2035 try stream.writeAll(" = ");
2036 try self.writeInstRef(stream, default_ref);
2037 }
2038 try stream.writeAll(",\n");
2039 }
2040
2041 self.indent -= 2;
2042 try stream.writeByteNTimes(' ', self.indent);
2043 try stream.writeAll("}) ");
2044 try self.writeSrc(stream, inst_data.src());
2045 }
2046
2047 fn writePlNodeSwitchBr(
2048 self: *Writer,
2049 stream: anytype,
2050 inst: Inst.Index,
2051 special_prong: SpecialProng,
2052 ) !void {
2053 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
2054 const extra = self.code.extraData(Inst.SwitchBlock, inst_data.payload_index);
2055 const special: struct {
2056 body: []const Inst.Index,
2057 end: usize,
2058 } = switch (special_prong) {
2059 .none => .{ .body = &.{}, .end = extra.end },
2060 .under, .@"else" => blk: {
2061 const body_len = self.code.extra[extra.end];
2062 const extra_body_start = extra.end + 1;
2063 break :blk .{
2064 .body = self.code.extra[extra_body_start..][0..body_len],
2065 .end = extra_body_start + body_len,
2066 };
2067 },
2068 };
2069
2070 try self.writeInstRef(stream, extra.data.operand);
2071
2072 if (special.body.len != 0) {
2073 const prong_name = switch (special_prong) {
2074 .@"else" => "else",
2075 .under => "_",
2076 else => unreachable,
2077 };
2078 try stream.print(", {s} => {{\n", .{prong_name});
2079 self.indent += 2;
2080 try self.writeBody(stream, special.body);
2081 self.indent -= 2;
2082 try stream.writeByteNTimes(' ', self.indent);
2083 try stream.writeAll("}");
2084 }
2085
2086 var extra_index: usize = special.end;
2087 {
2088 var scalar_i: usize = 0;
2089 while (scalar_i < extra.data.cases_len) : (scalar_i += 1) {
2090 const item_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
2091 extra_index += 1;
2092 const body_len = self.code.extra[extra_index];
2093 extra_index += 1;
2094 const body = self.code.extra[extra_index..][0..body_len];
2095 extra_index += body_len;
2096
2097 try stream.writeAll(", ");
2098 try self.writeInstRef(stream, item_ref);
2099 try stream.writeAll(" => {\n");
2100 self.indent += 2;
2101 try self.writeBody(stream, body);
2102 self.indent -= 2;
2103 try stream.writeByteNTimes(' ', self.indent);
2104 try stream.writeAll("}");
2105 }
2106 }
2107 try stream.writeAll(") ");
2108 try self.writeSrc(stream, inst_data.src());
2109 }
2110
2111 fn writePlNodeSwitchBlockMulti(
2112 self: *Writer,
2113 stream: anytype,
2114 inst: Inst.Index,
2115 special_prong: SpecialProng,
2116 ) !void {
2117 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
2118 const extra = self.code.extraData(Inst.SwitchBlockMulti, inst_data.payload_index);
2119 const special: struct {
2120 body: []const Inst.Index,
2121 end: usize,
2122 } = switch (special_prong) {
2123 .none => .{ .body = &.{}, .end = extra.end },
2124 .under, .@"else" => blk: {
2125 const body_len = self.code.extra[extra.end];
2126 const extra_body_start = extra.end + 1;
2127 break :blk .{
2128 .body = self.code.extra[extra_body_start..][0..body_len],
2129 .end = extra_body_start + body_len,
2130 };
2131 },
2132 };
2133
2134 try self.writeInstRef(stream, extra.data.operand);
2135
2136 if (special.body.len != 0) {
2137 const prong_name = switch (special_prong) {
2138 .@"else" => "else",
2139 .under => "_",
2140 else => unreachable,
2141 };
2142 try stream.print(", {s} => {{\n", .{prong_name});
2143 self.indent += 2;
2144 try self.writeBody(stream, special.body);
2145 self.indent -= 2;
2146 try stream.writeByteNTimes(' ', self.indent);
2147 try stream.writeAll("}");
2148 }
2149
2150 var extra_index: usize = special.end;
2151 {
2152 var scalar_i: usize = 0;
2153 while (scalar_i < extra.data.scalar_cases_len) : (scalar_i += 1) {
2154 const item_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
2155 extra_index += 1;
2156 const body_len = self.code.extra[extra_index];
2157 extra_index += 1;
2158 const body = self.code.extra[extra_index..][0..body_len];
2159 extra_index += body_len;
2160
2161 try stream.writeAll(", ");
2162 try self.writeInstRef(stream, item_ref);
2163 try stream.writeAll(" => {\n");
2164 self.indent += 2;
2165 try self.writeBody(stream, body);
2166 self.indent -= 2;
2167 try stream.writeByteNTimes(' ', self.indent);
2168 try stream.writeAll("}");
2169 }
2170 }
2171 {
2172 var multi_i: usize = 0;
2173 while (multi_i < extra.data.multi_cases_len) : (multi_i += 1) {
2174 const items_len = self.code.extra[extra_index];
2175 extra_index += 1;
2176 const ranges_len = self.code.extra[extra_index];
2177 extra_index += 1;
2178 const body_len = self.code.extra[extra_index];
2179 extra_index += 1;
2180 const items = self.code.refSlice(extra_index, items_len);
2181 extra_index += items_len;
2182
2183 for (items) |item_ref| {
2184 try stream.writeAll(", ");
2185 try self.writeInstRef(stream, item_ref);
2186 }
2187
2188 var range_i: usize = 0;
2189 while (range_i < ranges_len) : (range_i += 1) {
2190 const item_first = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
2191 extra_index += 1;
2192 const item_last = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
2193 extra_index += 1;
2194
2195 try stream.writeAll(", ");
2196 try self.writeInstRef(stream, item_first);
2197 try stream.writeAll("...");
2198 try self.writeInstRef(stream, item_last);
2199 }
2200
2201 const body = self.code.extra[extra_index..][0..body_len];
2202 extra_index += body_len;
2203 try stream.writeAll(" => {\n");
2204 self.indent += 2;
2205 try self.writeBody(stream, body);
2206 self.indent -= 2;
2207 try stream.writeByteNTimes(' ', self.indent);
2208 try stream.writeAll("}");
2209 }
2210 }
2211 try stream.writeAll(") ");
2212 try self.writeSrc(stream, inst_data.src());
2213 }
2214
2215 fn writePlNodeMultiOp(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2216 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
2217 const extra = self.code.extraData(Inst.MultiOp, inst_data.payload_index);
2218 const operands = self.code.refSlice(extra.end, extra.data.operands_len);
2219
2220 for (operands) |operand, i| {
2221 if (i != 0) try stream.writeAll(", ");
2222 try self.writeInstRef(stream, operand);
2223 }
2224 try stream.writeAll(") ");
2225 try self.writeSrc(stream, inst_data.src());
2226 }
2227
2228 fn writePlNodeDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2229 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
2230 const owner_decl = self.scope.ownerDecl().?;
2231 const decl = owner_decl.dependencies.entries.items[inst_data.payload_index].key;
2232 try stream.print("{s}) ", .{decl.name});
2233 try self.writeSrc(stream, inst_data.src());
2234 }
2235
2236 fn writePlNodeField(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2237 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
2238 const extra = self.code.extraData(Inst.Field, inst_data.payload_index).data;
2239 const name = self.code.nullTerminatedString(extra.field_name_start);
2240 try self.writeInstRef(stream, extra.lhs);
2241 try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(name)});
2242 try self.writeSrc(stream, inst_data.src());
2243 }
2244
2245 fn writeAs(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2246 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
2247 const extra = self.code.extraData(Inst.As, inst_data.payload_index).data;
2248 try self.writeInstRef(stream, extra.dest_type);
2249 try stream.writeAll(", ");
2250 try self.writeInstRef(stream, extra.operand);
2251 try stream.writeAll(") ");
2252 try self.writeSrc(stream, inst_data.src());
2253 }
2254
2255 fn writeNode(
2256 self: *Writer,
2257 stream: anytype,
2258 inst: Inst.Index,
2259 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
2260 const src_node = self.code.instructions.items(.data)[inst].node;
2261 const src: LazySrcLoc = .{ .node_offset = src_node };
2262 try stream.writeAll(") ");
2263 try self.writeSrc(stream, src);
2264 }
2265
2266 fn writeStrTok(
2267 self: *Writer,
2268 stream: anytype,
2269 inst: Inst.Index,
2270 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
2271 const inst_data = self.code.instructions.items(.data)[inst].str_tok;
2272 const str = inst_data.get(self.code);
2273 try stream.print("\"{}\") ", .{std.zig.fmtEscapes(str)});
2274 try self.writeSrc(stream, inst_data.src());
2275 }
2276
2277 fn writeFnType(
2278 self: *Writer,
2279 stream: anytype,
2280 inst: Inst.Index,
2281 var_args: bool,
2282 ) !void {
2283 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
2284 const src = inst_data.src();
2285 const extra = self.code.extraData(Inst.FnType, inst_data.payload_index);
2286 const param_types = self.code.refSlice(extra.end, extra.data.param_types_len);
2287 return self.writeFnTypeCommon(stream, param_types, extra.data.return_type, var_args, .none, src);
2288 }
2289
2290 fn writeFnTypeCc(
2291 self: *Writer,
2292 stream: anytype,
2293 inst: Inst.Index,
2294 var_args: bool,
2295 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
2296 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
2297 const src = inst_data.src();
2298 const extra = self.code.extraData(Inst.FnTypeCc, inst_data.payload_index);
2299 const param_types = self.code.refSlice(extra.end, extra.data.param_types_len);
2300 const cc = extra.data.cc;
2301 return self.writeFnTypeCommon(stream, param_types, extra.data.return_type, var_args, cc, src);
2302 }
2303
2304 fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2305 const inst_data = self.code.instructions.items(.data)[inst].bool_br;
2306 const extra = self.code.extraData(Inst.Block, inst_data.payload_index);
2307 const body = self.code.extra[extra.end..][0..extra.data.body_len];
2308 try self.writeInstRef(stream, inst_data.lhs);
2309 try stream.writeAll(", {\n");
2310 self.indent += 2;
2311 try self.writeBody(stream, body);
2312 self.indent -= 2;
2313 try stream.writeByteNTimes(' ', self.indent);
2314 try stream.writeAll("})");
2315 }
2316
2317 fn writeIntType(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2318 const int_type = self.code.instructions.items(.data)[inst].int_type;
2319 const prefix: u8 = switch (int_type.signedness) {
2320 .signed => 'i',
2321 .unsigned => 'u',
2322 };
2323 try stream.print("{c}{d}) ", .{ prefix, int_type.bit_count });
2324 try self.writeSrc(stream, int_type.src());
2325 }
2326
2327 fn writeBreak(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2328 const inst_data = self.code.instructions.items(.data)[inst].@"break";
2329
2330 try self.writeInstIndex(stream, inst_data.block_inst);
2331 try stream.writeAll(", ");
2332 try self.writeInstRef(stream, inst_data.operand);
2333 try stream.writeAll(")");
2334 }
2335
2336 fn writeUnreachable(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2337 const inst_data = self.code.instructions.items(.data)[inst].@"unreachable";
2338 const safety_str = if (inst_data.safety) "safe" else "unsafe";
2339 try stream.print("{s}) ", .{safety_str});
2340 try self.writeSrc(stream, inst_data.src());
2341 }
2342
2343 fn writeFnTypeCommon(
2344 self: *Writer,
2345 stream: anytype,
2346 param_types: []const Inst.Ref,
2347 ret_ty: Inst.Ref,
2348 var_args: bool,
2349 cc: Inst.Ref,
2350 src: LazySrcLoc,
2351 ) !void {
2352 try stream.writeAll("[");
2353 for (param_types) |param_type, i| {
2354 if (i != 0) try stream.writeAll(", ");
2355 try self.writeInstRef(stream, param_type);
2356 }
2357 try stream.writeAll("], ");
2358 try self.writeInstRef(stream, ret_ty);
2359 try self.writeOptionalInstRef(stream, ", cc=", cc);
2360 try self.writeFlag(stream, ", var_args", var_args);
2361 try stream.writeAll(") ");
2362 try self.writeSrc(stream, src);
2363 }
2364
2365 fn writeSmallStr(
2366 self: *Writer,
2367 stream: anytype,
2368 inst: Inst.Index,
2369 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
2370 const str = self.code.instructions.items(.data)[inst].small_str.get();
2371 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});
2372 }
2373
2374 fn writeSwitchCapture(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2375 const inst_data = self.code.instructions.items(.data)[inst].switch_capture;
2376 try self.writeInstIndex(stream, inst_data.switch_inst);
2377 try stream.print(", {d})", .{inst_data.prong_index});
2378 }
2379
2380 fn writeInstRef(self: *Writer, stream: anytype, ref: Inst.Ref) !void {
2381 var i: usize = @enumToInt(ref);
2382
2383 if (i < Inst.Ref.typed_value_map.len) {
2384 return stream.print("@{}", .{ref});
2385 }
2386 i -= Inst.Ref.typed_value_map.len;
2387
2388 if (i < self.param_count) {
2389 return stream.print("${d}", .{i});
2390 }
2391 i -= self.param_count;
2392
2393 return self.writeInstIndex(stream, @intCast(Inst.Index, i));
2394 }
2395
2396 fn writeInstIndex(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2397 return stream.print("%{d}", .{inst});
2398 }
2399
2400 fn writeOptionalInstRef(
2401 self: *Writer,
2402 stream: anytype,
2403 prefix: []const u8,
2404 inst: Inst.Ref,
2405 ) !void {
2406 if (inst == .none) return;
2407 try stream.writeAll(prefix);
2408 try self.writeInstRef(stream, inst);
2409 }
2410
2411 fn writeFlag(
2412 self: *Writer,
2413 stream: anytype,
2414 name: []const u8,
2415 flag: bool,
2416 ) !void {
2417 if (!flag) return;
2418 try stream.writeAll(name);
2419 }
2420
2421 fn writeSrc(self: *Writer, stream: anytype, src: LazySrcLoc) !void {
2422 const tree = self.scope.tree();
2423 const src_loc = src.toSrcLoc(self.scope);
2424 const abs_byte_off = try src_loc.byteOffset();
2425 const delta_line = std.zig.findLineColumn(tree.source, abs_byte_off);
2426 try stream.print("{s}:{d}:{d}", .{
2427 @tagName(src), delta_line.line + 1, delta_line.column + 1,
2428 });
2429 }
2430
2431 fn writeBody(self: *Writer, stream: anytype, body: []const Inst.Index) !void {
2432 for (body) |inst| {
2433 try stream.writeByteNTimes(' ', self.indent);
2434 try stream.print("%{d} ", .{inst});
2435 try self.writeInstToStream(stream, inst);
2436 try stream.writeByte('\n');
2437 }
2438 }
2439};
test/behavior.zig created+153
...@@ -0,0 +1,153 @@
1const builtin = @import("builtin");
2
3comptime {
4 // Tests that pass for both.
5 {}
6
7 if (builtin.zig_is_stage2) {
8 // Tests that only pass for stage2.
9 } else {
10 // Tests that only pass for stage1.
11 _ = @import("behavior/align.zig");
12 _ = @import("behavior/alignof.zig");
13 _ = @import("behavior/array.zig");
14 if (builtin.os.tag != .wasi) {
15 _ = @import("behavior/asm.zig");
16 _ = @import("behavior/async_fn.zig");
17 }
18 _ = @import("behavior/atomics.zig");
19 _ = @import("behavior/await_struct.zig");
20 _ = @import("behavior/bit_shifting.zig");
21 _ = @import("behavior/bitcast.zig");
22 _ = @import("behavior/bitreverse.zig");
23 _ = @import("behavior/bool.zig");
24 _ = @import("behavior/bugs/1025.zig");
25 _ = @import("behavior/bugs/1076.zig");
26 _ = @import("behavior/bugs/1111.zig");
27 _ = @import("behavior/bugs/1120.zig");
28 _ = @import("behavior/bugs/1277.zig");
29 _ = @import("behavior/bugs/1310.zig");
30 _ = @import("behavior/bugs/1322.zig");
31 _ = @import("behavior/bugs/1381.zig");
32 _ = @import("behavior/bugs/1421.zig");
33 _ = @import("behavior/bugs/1442.zig");
34 _ = @import("behavior/bugs/1486.zig");
35 _ = @import("behavior/bugs/1500.zig");
36 _ = @import("behavior/bugs/1607.zig");
37 _ = @import("behavior/bugs/1735.zig");
38 _ = @import("behavior/bugs/1741.zig");
39 _ = @import("behavior/bugs/1851.zig");
40 _ = @import("behavior/bugs/1914.zig");
41 _ = @import("behavior/bugs/2006.zig");
42 _ = @import("behavior/bugs/2114.zig");
43 _ = @import("behavior/bugs/2346.zig");
44 _ = @import("behavior/bugs/2578.zig");
45 _ = @import("behavior/bugs/2692.zig");
46 _ = @import("behavior/bugs/2889.zig");
47 _ = @import("behavior/bugs/3007.zig");
48 _ = @import("behavior/bugs/3046.zig");
49 _ = @import("behavior/bugs/3112.zig");
50 _ = @import("behavior/bugs/3367.zig");
51 _ = @import("behavior/bugs/3384.zig");
52 _ = @import("behavior/bugs/3586.zig");
53 _ = @import("behavior/bugs/3742.zig");
54 _ = @import("behavior/bugs/4328.zig");
55 _ = @import("behavior/bugs/4560.zig");
56 _ = @import("behavior/bugs/4769_a.zig");
57 _ = @import("behavior/bugs/4769_b.zig");
58 _ = @import("behavior/bugs/4769_c.zig");
59 _ = @import("behavior/bugs/4954.zig");
60 _ = @import("behavior/bugs/5398.zig");
61 _ = @import("behavior/bugs/5413.zig");
62 _ = @import("behavior/bugs/5474.zig");
63 _ = @import("behavior/bugs/5487.zig");
64 _ = @import("behavior/bugs/6456.zig");
65 _ = @import("behavior/bugs/6781.zig");
66 _ = @import("behavior/bugs/6850.zig");
67 _ = @import("behavior/bugs/7027.zig");
68 _ = @import("behavior/bugs/7047.zig");
69 _ = @import("behavior/bugs/7003.zig");
70 _ = @import("behavior/bugs/7250.zig");
71 _ = @import("behavior/bugs/394.zig");
72 _ = @import("behavior/bugs/421.zig");
73 _ = @import("behavior/bugs/529.zig");
74 _ = @import("behavior/bugs/624.zig");
75 _ = @import("behavior/bugs/655.zig");
76 _ = @import("behavior/bugs/656.zig");
77 _ = @import("behavior/bugs/679.zig");
78 _ = @import("behavior/bugs/704.zig");
79 _ = @import("behavior/bugs/718.zig");
80 _ = @import("behavior/bugs/726.zig");
81 _ = @import("behavior/bugs/828.zig");
82 _ = @import("behavior/bugs/920.zig");
83 _ = @import("behavior/byteswap.zig");
84 _ = @import("behavior/byval_arg_var.zig");
85 _ = @import("behavior/call.zig");
86 _ = @import("behavior/cast.zig");
87 _ = @import("behavior/const_slice_child.zig");
88 _ = @import("behavior/defer.zig");
89 _ = @import("behavior/enum.zig");
90 _ = @import("behavior/enum_with_members.zig");
91 _ = @import("behavior/error.zig");
92 _ = @import("behavior/eval.zig");
93 _ = @import("behavior/field_parent_ptr.zig");
94 _ = @import("behavior/floatop.zig");
95 _ = @import("behavior/fn.zig");
96 _ = @import("behavior/fn_in_struct_in_comptime.zig");
97 _ = @import("behavior/fn_delegation.zig");
98 _ = @import("behavior/for.zig");
99 _ = @import("behavior/generics.zig");
100 _ = @import("behavior/hasdecl.zig");
101 _ = @import("behavior/hasfield.zig");
102 _ = @import("behavior/if.zig");
103 _ = @import("behavior/import.zig");
104 _ = @import("behavior/incomplete_struct_param_tld.zig");
105 _ = @import("behavior/inttoptr.zig");
106 _ = @import("behavior/ir_block_deps.zig");
107 _ = @import("behavior/math.zig");
108 _ = @import("behavior/merge_error_sets.zig");
109 _ = @import("behavior/misc.zig");
110 _ = @import("behavior/muladd.zig");
111 _ = @import("behavior/namespace_depends_on_compile_var.zig");
112 _ = @import("behavior/null.zig");
113 _ = @import("behavior/optional.zig");
114 _ = @import("behavior/pointers.zig");
115 _ = @import("behavior/popcount.zig");
116 _ = @import("behavior/ptrcast.zig");
117 _ = @import("behavior/pub_enum.zig");
118 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
119 _ = @import("behavior/reflection.zig");
120 _ = @import("behavior/shuffle.zig");
121 _ = @import("behavior/sizeof_and_typeof.zig");
122 _ = @import("behavior/slice.zig");
123 _ = @import("behavior/slice_sentinel_comptime.zig");
124 _ = @import("behavior/struct.zig");
125 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
126 _ = @import("behavior/struct_contains_slice_of_itself.zig");
127 _ = @import("behavior/switch.zig");
128 _ = @import("behavior/switch_prong_err_enum.zig");
129 _ = @import("behavior/switch_prong_implicit_cast.zig");
130 _ = @import("behavior/syntax.zig");
131 _ = @import("behavior/this.zig");
132 _ = @import("behavior/truncate.zig");
133 _ = @import("behavior/try.zig");
134 _ = @import("behavior/tuple.zig");
135 _ = @import("behavior/type.zig");
136 _ = @import("behavior/type_info.zig");
137 _ = @import("behavior/typename.zig");
138 _ = @import("behavior/undefined.zig");
139 _ = @import("behavior/underscore.zig");
140 _ = @import("behavior/union.zig");
141 _ = @import("behavior/usingnamespace.zig");
142 _ = @import("behavior/var_args.zig");
143 _ = @import("behavior/vector.zig");
144 _ = @import("behavior/void.zig");
145 if (builtin.target.cpu.arch == .wasm32) {
146 _ = @import("behavior/wasm.zig");
147 }
148 _ = @import("behavior/while.zig");
149 _ = @import("behavior/widening.zig");
150 _ = @import("behavior/src.zig");
151 _ = @import("behavior/translate_c_macros.zig");
152 }
153}
test/behavior/align.zig created+350
...@@ -0,0 +1,350 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const builtin = @import("builtin");
4const native_arch = builtin.target.cpu.arch;
5
6var foo: u8 align(4) = 100;
7
8test "global variable alignment" {
9 comptime try expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4);
10 comptime try expect(@TypeOf(&foo) == *align(4) u8);
11 {
12 const slice = @as(*[1]u8, &foo)[0..];
13 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
14 }
15 {
16 var runtime_zero: usize = 0;
17 const slice = @as(*[1]u8, &foo)[runtime_zero..];
18 comptime try expect(@TypeOf(slice) == []align(4) u8);
19 }
20}
21
22fn derp() align(@sizeOf(usize) * 2) i32 {
23 return 1234;
24}
25fn noop1() align(1) void {}
26fn noop4() align(4) void {}
27
28test "function alignment" {
29 // function alignment is a compile error on wasm32/wasm64
30 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
31
32 try expect(derp() == 1234);
33 try expect(@TypeOf(noop1) == fn () align(1) void);
34 try expect(@TypeOf(noop4) == fn () align(4) void);
35 noop1();
36 noop4();
37}
38
39var baz: packed struct {
40 a: u32,
41 b: u32,
42} = undefined;
43
44test "packed struct alignment" {
45 try expect(@TypeOf(&baz.b) == *align(1) u32);
46}
47
48const blah: packed struct {
49 a: u3,
50 b: u3,
51 c: u2,
52} = undefined;
53
54test "bit field alignment" {
55 try expect(@TypeOf(&blah.b) == *align(1:3:1) const u3);
56}
57
58test "default alignment allows unspecified in type syntax" {
59 try expect(*u32 == *align(@alignOf(u32)) u32);
60}
61
62test "implicitly decreasing pointer alignment" {
63 const a: u32 align(4) = 3;
64 const b: u32 align(8) = 4;
65 try expect(addUnaligned(&a, &b) == 7);
66}
67
68fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
69 return a.* + b.*;
70}
71
72test "implicitly decreasing slice alignment" {
73 const a: u32 align(4) = 3;
74 const b: u32 align(8) = 4;
75 try expect(addUnalignedSlice(@as(*const [1]u32, &a)[0..], @as(*const [1]u32, &b)[0..]) == 7);
76}
77fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
78 return a[0] + b[0];
79}
80
81test "specifying alignment allows pointer cast" {
82 try testBytesAlign(0x33);
83}
84fn testBytesAlign(b: u8) !void {
85 var bytes align(4) = [_]u8{
86 b,
87 b,
88 b,
89 b,
90 };
91 const ptr = @ptrCast(*u32, &bytes[0]);
92 try expect(ptr.* == 0x33333333);
93}
94
95test "@alignCast pointers" {
96 var x: u32 align(4) = 1;
97 expectsOnly1(&x);
98 try expect(x == 2);
99}
100fn expectsOnly1(x: *align(1) u32) void {
101 expects4(@alignCast(4, x));
102}
103fn expects4(x: *align(4) u32) void {
104 x.* += 1;
105}
106
107test "@alignCast slices" {
108 var array align(4) = [_]u32{
109 1,
110 1,
111 };
112 const slice = array[0..];
113 sliceExpectsOnly1(slice);
114 try expect(slice[0] == 2);
115}
116fn sliceExpectsOnly1(slice: []align(1) u32) void {
117 sliceExpects4(@alignCast(4, slice));
118}
119fn sliceExpects4(slice: []align(4) u32) void {
120 slice[0] += 1;
121}
122
123test "implicitly decreasing fn alignment" {
124 // function alignment is a compile error on wasm32/wasm64
125 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
126
127 try testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
128 try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
129}
130
131fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) !void {
132 try expect(ptr() == answer);
133}
134
135fn alignedSmall() align(8) i32 {
136 return 1234;
137}
138fn alignedBig() align(16) i32 {
139 return 5678;
140}
141
142test "@alignCast functions" {
143 // function alignment is a compile error on wasm32/wasm64
144 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
145 if (native_arch == .thumb) return error.SkipZigTest;
146
147 try expect(fnExpectsOnly1(simple4) == 0x19);
148}
149fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
150 return fnExpects4(@alignCast(4, ptr));
151}
152fn fnExpects4(ptr: fn () align(4) i32) i32 {
153 return ptr();
154}
155fn simple4() align(4) i32 {
156 return 0x19;
157}
158
159test "generic function with align param" {
160 // function alignment is a compile error on wasm32/wasm64
161 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
162 if (native_arch == .thumb) return error.SkipZigTest;
163
164 try expect(whyWouldYouEverDoThis(1) == 0x1);
165 try expect(whyWouldYouEverDoThis(4) == 0x1);
166 try expect(whyWouldYouEverDoThis(8) == 0x1);
167}
168
169fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
170 return 0x1;
171}
172
173test "@ptrCast preserves alignment of bigger source" {
174 var x: u32 align(16) = 1234;
175 const ptr = @ptrCast(*u8, &x);
176 try expect(@TypeOf(ptr) == *align(16) u8);
177}
178
179test "runtime known array index has best alignment possible" {
180 // take full advantage of over-alignment
181 var array align(4) = [_]u8{ 1, 2, 3, 4 };
182 try expect(@TypeOf(&array[0]) == *align(4) u8);
183 try expect(@TypeOf(&array[1]) == *u8);
184 try expect(@TypeOf(&array[2]) == *align(2) u8);
185 try expect(@TypeOf(&array[3]) == *u8);
186
187 // because align is too small but we still figure out to use 2
188 var bigger align(2) = [_]u64{ 1, 2, 3, 4 };
189 try expect(@TypeOf(&bigger[0]) == *align(2) u64);
190 try expect(@TypeOf(&bigger[1]) == *align(2) u64);
191 try expect(@TypeOf(&bigger[2]) == *align(2) u64);
192 try expect(@TypeOf(&bigger[3]) == *align(2) u64);
193
194 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
195 var smaller align(2) = [_]u32{ 1, 2, 3, 4 };
196 var runtime_zero: usize = 0;
197 comptime try expect(@TypeOf(smaller[runtime_zero..]) == []align(2) u32);
198 comptime try expect(@TypeOf(smaller[runtime_zero..].ptr) == [*]align(2) u32);
199 try testIndex(smaller[runtime_zero..].ptr, 0, *align(2) u32);
200 try testIndex(smaller[runtime_zero..].ptr, 1, *align(2) u32);
201 try testIndex(smaller[runtime_zero..].ptr, 2, *align(2) u32);
202 try testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32);
203
204 // has to use ABI alignment because index known at runtime only
205 try testIndex2(array[runtime_zero..].ptr, 0, *u8);
206 try testIndex2(array[runtime_zero..].ptr, 1, *u8);
207 try testIndex2(array[runtime_zero..].ptr, 2, *u8);
208 try testIndex2(array[runtime_zero..].ptr, 3, *u8);
209}
210fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) !void {
211 comptime try expect(@TypeOf(&smaller[index]) == T);
212}
213fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {
214 comptime try expect(@TypeOf(&ptr[index]) == T);
215}
216
217test "alignstack" {
218 try expect(fnWithAlignedStack() == 1234);
219}
220
221fn fnWithAlignedStack() i32 {
222 @setAlignStack(256);
223 return 1234;
224}
225
226test "alignment of structs" {
227 try expect(@alignOf(struct {
228 a: i32,
229 b: *i32,
230 }) == @alignOf(usize));
231}
232
233test "alignment of function with c calling convention" {
234 var runtime_nothing = nothing;
235 const casted1 = @ptrCast(*const u8, runtime_nothing);
236 const casted2 = @ptrCast(fn () callconv(.C) void, casted1);
237 casted2();
238}
239
240fn nothing() callconv(.C) void {}
241
242test "return error union with 128-bit integer" {
243 try expect(3 == try give());
244}
245fn give() anyerror!u128 {
246 return 3;
247}
248
249test "alignment of >= 128-bit integer type" {
250 try expect(@alignOf(u128) == 16);
251 try expect(@alignOf(u129) == 16);
252}
253
254test "alignment of struct with 128-bit field" {
255 try expect(@alignOf(struct {
256 x: u128,
257 }) == 16);
258
259 comptime {
260 try expect(@alignOf(struct {
261 x: u128,
262 }) == 16);
263 }
264}
265
266test "size of extern struct with 128-bit field" {
267 try expect(@sizeOf(extern struct {
268 x: u128,
269 y: u8,
270 }) == 32);
271
272 comptime {
273 try expect(@sizeOf(extern struct {
274 x: u128,
275 y: u8,
276 }) == 32);
277 }
278}
279
280const DefaultAligned = struct {
281 nevermind: u32,
282 badguy: i128,
283};
284
285test "read 128-bit field from default aligned struct in stack memory" {
286 var default_aligned = DefaultAligned{
287 .nevermind = 1,
288 .badguy = 12,
289 };
290 try expect((@ptrToInt(&default_aligned.badguy) % 16) == 0);
291 try expect(12 == default_aligned.badguy);
292}
293
294var default_aligned_global = DefaultAligned{
295 .nevermind = 1,
296 .badguy = 12,
297};
298
299test "read 128-bit field from default aligned struct in global memory" {
300 try expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0);
301 try expect(12 == default_aligned_global.badguy);
302}
303
304test "struct field explicit alignment" {
305 const S = struct {
306 const Node = struct {
307 next: *Node,
308 massive_byte: u8 align(64),
309 };
310 };
311
312 var node: S.Node = undefined;
313 node.massive_byte = 100;
314 try expect(node.massive_byte == 100);
315 comptime try expect(@TypeOf(&node.massive_byte) == *align(64) u8);
316 try expect(@ptrToInt(&node.massive_byte) % 64 == 0);
317}
318
319test "align(@alignOf(T)) T does not force resolution of T" {
320 const S = struct {
321 const A = struct {
322 a: *align(@alignOf(A)) A,
323 };
324 fn doTheTest() void {
325 suspend {
326 resume @frame();
327 }
328 _ = bar(@Frame(doTheTest));
329 }
330 fn bar(comptime T: type) *align(@alignOf(T)) T {
331 ok = true;
332 return undefined;
333 }
334
335 var ok = false;
336 };
337 _ = async S.doTheTest();
338 try expect(S.ok);
339}
340
341test "align(N) on functions" {
342 // function alignment is a compile error on wasm32/wasm64
343 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
344 if (native_arch == .thumb) return error.SkipZigTest;
345
346 try expect((@ptrToInt(overaligned_fn) & (0x1000 - 1)) == 0);
347}
348fn overaligned_fn() align(0x1000) i32 {
349 return 42;
350}
test/behavior/alignof.zig created+39
...@@ -0,0 +1,39 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const builtin = @import("builtin");
4const native_arch = builtin.target.cpu.arch;
5const maxInt = std.math.maxInt;
6
7const Foo = struct {
8 x: u32,
9 y: u32,
10 z: u32,
11};
12
13test "@alignOf(T) before referencing T" {
14 comptime try expect(@alignOf(Foo) != maxInt(usize));
15 if (native_arch == .x86_64) {
16 comptime try expect(@alignOf(Foo) == 4);
17 }
18}
19
20test "comparison of @alignOf(T) against zero" {
21 {
22 const T = struct { x: u32 };
23 try expect(!(@alignOf(T) == 0));
24 try expect(@alignOf(T) != 0);
25 try expect(!(@alignOf(T) < 0));
26 try expect(!(@alignOf(T) <= 0));
27 try expect(@alignOf(T) > 0);
28 try expect(@alignOf(T) >= 0);
29 }
30 {
31 const T = struct {};
32 try expect(@alignOf(T) == 0);
33 try expect(!(@alignOf(T) != 0));
34 try expect(!(@alignOf(T) < 0));
35 try expect(@alignOf(T) <= 0);
36 try expect(!(@alignOf(T) > 0));
37 try expect(@alignOf(T) >= 0);
38 }
39}
test/behavior/array.zig created+489
...@@ -0,0 +1,489 @@
1const std = @import("std");
2const testing = std.testing;
3const mem = std.mem;
4const expect = testing.expect;
5const expectEqual = testing.expectEqual;
6
7test "arrays" {
8 var array: [5]u32 = undefined;
9
10 var i: u32 = 0;
11 while (i < 5) {
12 array[i] = i + 1;
13 i = array[i];
14 }
15
16 i = 0;
17 var accumulator = @as(u32, 0);
18 while (i < 5) {
19 accumulator += array[i];
20
21 i += 1;
22 }
23
24 try expect(accumulator == 15);
25 try expect(getArrayLen(&array) == 5);
26}
27fn getArrayLen(a: []const u32) usize {
28 return a.len;
29}
30
31test "array with sentinels" {
32 const S = struct {
33 fn doTheTest(is_ct: bool) !void {
34 if (is_ct) {
35 var zero_sized: [0:0xde]u8 = [_:0xde]u8{};
36 // Disabled at runtime because of
37 // https://github.com/ziglang/zig/issues/4372
38 try expectEqual(@as(u8, 0xde), zero_sized[0]);
39 var reinterpreted = @ptrCast(*[1]u8, &zero_sized);
40 try expectEqual(@as(u8, 0xde), reinterpreted[0]);
41 }
42 var arr: [3:0x55]u8 = undefined;
43 // Make sure the sentinel pointer is pointing after the last element
44 if (!is_ct) {
45 const sentinel_ptr = @ptrToInt(&arr[3]);
46 const last_elem_ptr = @ptrToInt(&arr[2]);
47 try expectEqual(@as(usize, 1), sentinel_ptr - last_elem_ptr);
48 }
49 // Make sure the sentinel is writeable
50 arr[3] = 0x55;
51 }
52 };
53
54 try S.doTheTest(false);
55 comptime try S.doTheTest(true);
56}
57
58test "void arrays" {
59 var array: [4]void = undefined;
60 array[0] = void{};
61 array[1] = array[2];
62 try expect(@sizeOf(@TypeOf(array)) == 0);
63 try expect(array.len == 4);
64}
65
66test "array literal" {
67 const hex_mult = [_]u16{
68 4096,
69 256,
70 16,
71 1,
72 };
73
74 try expect(hex_mult.len == 4);
75 try expect(hex_mult[1] == 256);
76}
77
78test "array dot len const expr" {
79 try expect(comptime x: {
80 break :x some_array.len == 4;
81 });
82}
83
84const ArrayDotLenConstExpr = struct {
85 y: [some_array.len]u8,
86};
87const some_array = [_]u8{
88 0,
89 1,
90 2,
91 3,
92};
93
94test "nested arrays" {
95 const array_of_strings = [_][]const u8{
96 "hello",
97 "this",
98 "is",
99 "my",
100 "thing",
101 };
102 for (array_of_strings) |s, i| {
103 if (i == 0) try expect(mem.eql(u8, s, "hello"));
104 if (i == 1) try expect(mem.eql(u8, s, "this"));
105 if (i == 2) try expect(mem.eql(u8, s, "is"));
106 if (i == 3) try expect(mem.eql(u8, s, "my"));
107 if (i == 4) try expect(mem.eql(u8, s, "thing"));
108 }
109}
110
111var s_array: [8]Sub = undefined;
112const Sub = struct {
113 b: u8,
114};
115const Str = struct {
116 a: []Sub,
117};
118test "set global var array via slice embedded in struct" {
119 var s = Str{ .a = s_array[0..] };
120
121 s.a[0].b = 1;
122 s.a[1].b = 2;
123 s.a[2].b = 3;
124
125 try expect(s_array[0].b == 1);
126 try expect(s_array[1].b == 2);
127 try expect(s_array[2].b == 3);
128}
129
130test "array literal with specified size" {
131 var array = [2]u8{
132 1,
133 2,
134 };
135 try expect(array[0] == 1);
136 try expect(array[1] == 2);
137}
138
139test "array len field" {
140 var arr = [4]u8{ 0, 0, 0, 0 };
141 var ptr = &arr;
142 try expect(arr.len == 4);
143 comptime try expect(arr.len == 4);
144 try expect(ptr.len == 4);
145 comptime try expect(ptr.len == 4);
146}
147
148test "single-item pointer to array indexing and slicing" {
149 try testSingleItemPtrArrayIndexSlice();
150 comptime try testSingleItemPtrArrayIndexSlice();
151}
152
153fn testSingleItemPtrArrayIndexSlice() !void {
154 {
155 var array: [4]u8 = "aaaa".*;
156 doSomeMangling(&array);
157 try expect(mem.eql(u8, "azya", &array));
158 }
159 {
160 var array = "aaaa".*;
161 doSomeMangling(&array);
162 try expect(mem.eql(u8, "azya", &array));
163 }
164}
165
166fn doSomeMangling(array: *[4]u8) void {
167 array[1] = 'z';
168 array[2..3][0] = 'y';
169}
170
171test "implicit cast single-item pointer" {
172 try testImplicitCastSingleItemPtr();
173 comptime try testImplicitCastSingleItemPtr();
174}
175
176fn testImplicitCastSingleItemPtr() !void {
177 var byte: u8 = 100;
178 const slice = @as(*[1]u8, &byte)[0..];
179 slice[0] += 1;
180 try expect(byte == 101);
181}
182
183fn testArrayByValAtComptime(b: [2]u8) u8 {
184 return b[0];
185}
186
187test "comptime evalutating function that takes array by value" {
188 const arr = [_]u8{ 0, 1 };
189 _ = comptime testArrayByValAtComptime(arr);
190 _ = comptime testArrayByValAtComptime(arr);
191}
192
193test "implicit comptime in array type size" {
194 var arr: [plusOne(10)]bool = undefined;
195 try expect(arr.len == 11);
196}
197
198fn plusOne(x: u32) u32 {
199 return x + 1;
200}
201
202test "runtime initialize array elem and then implicit cast to slice" {
203 var two: i32 = 2;
204 const x: []const i32 = &[_]i32{two};
205 try expect(x[0] == 2);
206}
207
208test "array literal as argument to function" {
209 const S = struct {
210 fn entry(two: i32) !void {
211 try foo(&[_]i32{
212 1,
213 2,
214 3,
215 });
216 try foo(&[_]i32{
217 1,
218 two,
219 3,
220 });
221 try foo2(true, &[_]i32{
222 1,
223 2,
224 3,
225 });
226 try foo2(true, &[_]i32{
227 1,
228 two,
229 3,
230 });
231 }
232 fn foo(x: []const i32) !void {
233 try expect(x[0] == 1);
234 try expect(x[1] == 2);
235 try expect(x[2] == 3);
236 }
237 fn foo2(trash: bool, x: []const i32) !void {
238 try expect(trash);
239 try expect(x[0] == 1);
240 try expect(x[1] == 2);
241 try expect(x[2] == 3);
242 }
243 };
244 try S.entry(2);
245 comptime try S.entry(2);
246}
247
248test "double nested array to const slice cast in array literal" {
249 const S = struct {
250 fn entry(two: i32) !void {
251 const cases = [_][]const []const i32{
252 &[_][]const i32{&[_]i32{1}},
253 &[_][]const i32{&[_]i32{ 2, 3 }},
254 &[_][]const i32{
255 &[_]i32{4},
256 &[_]i32{ 5, 6, 7 },
257 },
258 };
259 try check(&cases);
260
261 const cases2 = [_][]const i32{
262 &[_]i32{1},
263 &[_]i32{ two, 3 },
264 };
265 try expect(cases2.len == 2);
266 try expect(cases2[0].len == 1);
267 try expect(cases2[0][0] == 1);
268 try expect(cases2[1].len == 2);
269 try expect(cases2[1][0] == 2);
270 try expect(cases2[1][1] == 3);
271
272 const cases3 = [_][]const []const i32{
273 &[_][]const i32{&[_]i32{1}},
274 &[_][]const i32{&[_]i32{ two, 3 }},
275 &[_][]const i32{
276 &[_]i32{4},
277 &[_]i32{ 5, 6, 7 },
278 },
279 };
280 try check(&cases3);
281 }
282
283 fn check(cases: []const []const []const i32) !void {
284 try expect(cases.len == 3);
285 try expect(cases[0].len == 1);
286 try expect(cases[0][0].len == 1);
287 try expect(cases[0][0][0] == 1);
288 try expect(cases[1].len == 1);
289 try expect(cases[1][0].len == 2);
290 try expect(cases[1][0][0] == 2);
291 try expect(cases[1][0][1] == 3);
292 try expect(cases[2].len == 2);
293 try expect(cases[2][0].len == 1);
294 try expect(cases[2][0][0] == 4);
295 try expect(cases[2][1].len == 3);
296 try expect(cases[2][1][0] == 5);
297 try expect(cases[2][1][1] == 6);
298 try expect(cases[2][1][2] == 7);
299 }
300 };
301 try S.entry(2);
302 comptime try S.entry(2);
303}
304
305test "read/write through global variable array of struct fields initialized via array mult" {
306 const S = struct {
307 fn doTheTest() !void {
308 try expect(storage[0].term == 1);
309 storage[0] = MyStruct{ .term = 123 };
310 try expect(storage[0].term == 123);
311 }
312
313 pub const MyStruct = struct {
314 term: usize,
315 };
316
317 var storage: [1]MyStruct = [_]MyStruct{MyStruct{ .term = 1 }} ** 1;
318 };
319 try S.doTheTest();
320}
321
322test "implicit cast zero sized array ptr to slice" {
323 {
324 var b = "".*;
325 const c: []const u8 = &b;
326 try expect(c.len == 0);
327 }
328 {
329 var b: [0]u8 = "".*;
330 const c: []const u8 = &b;
331 try expect(c.len == 0);
332 }
333}
334
335test "anonymous list literal syntax" {
336 const S = struct {
337 fn doTheTest() !void {
338 var array: [4]u8 = .{ 1, 2, 3, 4 };
339 try expect(array[0] == 1);
340 try expect(array[1] == 2);
341 try expect(array[2] == 3);
342 try expect(array[3] == 4);
343 }
344 };
345 try S.doTheTest();
346 comptime try S.doTheTest();
347}
348
349test "anonymous literal in array" {
350 const S = struct {
351 const Foo = struct {
352 a: usize = 2,
353 b: usize = 4,
354 };
355 fn doTheTest() !void {
356 var array: [2]Foo = .{
357 .{ .a = 3 },
358 .{ .b = 3 },
359 };
360 try expect(array[0].a == 3);
361 try expect(array[0].b == 4);
362 try expect(array[1].a == 2);
363 try expect(array[1].b == 3);
364 }
365 };
366 try S.doTheTest();
367 comptime try S.doTheTest();
368}
369
370test "access the null element of a null terminated array" {
371 const S = struct {
372 fn doTheTest() !void {
373 var array: [4:0]u8 = .{ 'a', 'o', 'e', 'u' };
374 try expect(array[4] == 0);
375 var len: usize = 4;
376 try expect(array[len] == 0);
377 }
378 };
379 try S.doTheTest();
380 comptime try S.doTheTest();
381}
382
383test "type deduction for array subscript expression" {
384 const S = struct {
385 fn doTheTest() !void {
386 var array = [_]u8{ 0x55, 0xAA };
387 var v0 = true;
388 try expectEqual(@as(u8, 0xAA), array[if (v0) 1 else 0]);
389 var v1 = false;
390 try expectEqual(@as(u8, 0x55), array[if (v1) 1 else 0]);
391 }
392 };
393 try S.doTheTest();
394 comptime try S.doTheTest();
395}
396
397test "sentinel element count towards the ABI size calculation" {
398 const S = struct {
399 fn doTheTest() !void {
400 const T = packed struct {
401 fill_pre: u8 = 0x55,
402 data: [0:0]u8 = undefined,
403 fill_post: u8 = 0xAA,
404 };
405 var x = T{};
406 var as_slice = mem.asBytes(&x);
407 try expectEqual(@as(usize, 3), as_slice.len);
408 try expectEqual(@as(u8, 0x55), as_slice[0]);
409 try expectEqual(@as(u8, 0xAA), as_slice[2]);
410 }
411 };
412
413 try S.doTheTest();
414 comptime try S.doTheTest();
415}
416
417test "zero-sized array with recursive type definition" {
418 const U = struct {
419 fn foo(comptime T: type, comptime n: usize) type {
420 return struct {
421 s: [n]T,
422 x: usize = n,
423 };
424 }
425 };
426
427 const S = struct {
428 list: U.foo(@This(), 0),
429 };
430
431 var t: S = .{ .list = .{ .s = undefined } };
432 try expectEqual(@as(usize, 0), t.list.x);
433}
434
435test "type coercion of anon struct literal to array" {
436 const S = struct {
437 const U = union {
438 a: u32,
439 b: bool,
440 c: []const u8,
441 };
442
443 fn doTheTest() !void {
444 var x1: u8 = 42;
445 const t1 = .{ x1, 56, 54 };
446 var arr1: [3]u8 = t1;
447 try expect(arr1[0] == 42);
448 try expect(arr1[1] == 56);
449 try expect(arr1[2] == 54);
450
451 var x2: U = .{ .a = 42 };
452 const t2 = .{ x2, .{ .b = true }, .{ .c = "hello" } };
453 var arr2: [3]U = t2;
454 try expect(arr2[0].a == 42);
455 try expect(arr2[1].b == true);
456 try expect(mem.eql(u8, arr2[2].c, "hello"));
457 }
458 };
459 try S.doTheTest();
460 comptime try S.doTheTest();
461}
462
463test "type coercion of pointer to anon struct literal to pointer to array" {
464 const S = struct {
465 const U = union {
466 a: u32,
467 b: bool,
468 c: []const u8,
469 };
470
471 fn doTheTest() !void {
472 var x1: u8 = 42;
473 const t1 = &.{ x1, 56, 54 };
474 var arr1: *const [3]u8 = t1;
475 try expect(arr1[0] == 42);
476 try expect(arr1[1] == 56);
477 try expect(arr1[2] == 54);
478
479 var x2: U = .{ .a = 42 };
480 const t2 = &.{ x2, .{ .b = true }, .{ .c = "hello" } };
481 var arr2: *const [3]U = t2;
482 try expect(arr2[0].a == 42);
483 try expect(arr2[1].b == true);
484 try expect(mem.eql(u8, arr2[2].c, "hello"));
485 }
486 };
487 try S.doTheTest();
488 comptime try S.doTheTest();
489}
test/behavior/asm.zig created+109
...@@ -0,0 +1,109 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const is_x86_64_linux = std.Target.current.cpu.arch == .x86_64 and std.Target.current.os.tag == .linux;
5
6comptime {
7 if (is_x86_64_linux) {
8 asm (
9 \\.globl this_is_my_alias;
10 \\.type this_is_my_alias, @function;
11 \\.set this_is_my_alias, derp;
12 );
13 }
14}
15
16test "module level assembly" {
17 if (is_x86_64_linux) {
18 try expect(this_is_my_alias() == 1234);
19 }
20}
21
22test "output constraint modifiers" {
23 // This is only testing compilation.
24 var a: u32 = 3;
25 asm volatile (""
26 : [_] "=m,r" (a)
27 :
28 : ""
29 );
30 asm volatile (""
31 : [_] "=r,m" (a)
32 :
33 : ""
34 );
35}
36
37test "alternative constraints" {
38 // Make sure we allow commas as a separator for alternative constraints.
39 var a: u32 = 3;
40 asm volatile (""
41 : [_] "=r,m" (a)
42 : [_] "r,m" (a)
43 : ""
44 );
45}
46
47test "sized integer/float in asm input" {
48 asm volatile (""
49 :
50 : [_] "m" (@as(usize, 3))
51 : ""
52 );
53 asm volatile (""
54 :
55 : [_] "m" (@as(i15, -3))
56 : ""
57 );
58 asm volatile (""
59 :
60 : [_] "m" (@as(u3, 3))
61 : ""
62 );
63 asm volatile (""
64 :
65 : [_] "m" (@as(i3, 3))
66 : ""
67 );
68 asm volatile (""
69 :
70 : [_] "m" (@as(u121, 3))
71 : ""
72 );
73 asm volatile (""
74 :
75 : [_] "m" (@as(i121, 3))
76 : ""
77 );
78 asm volatile (""
79 :
80 : [_] "m" (@as(f32, 3.17))
81 : ""
82 );
83 asm volatile (""
84 :
85 : [_] "m" (@as(f64, 3.17))
86 : ""
87 );
88}
89
90test "struct/array/union types as input values" {
91 asm volatile (""
92 :
93 : [_] "m" (@as([1]u32, undefined))
94 ); // fails
95 asm volatile (""
96 :
97 : [_] "m" (@as(struct { x: u32, y: u8 }, undefined))
98 ); // fails
99 asm volatile (""
100 :
101 : [_] "m" (@as(union { x: u32, y: u8 }, undefined))
102 ); // fails
103}
104
105extern fn this_is_my_alias() i32;
106
107export fn derp() i32 {
108 return 1234;
109}
test/behavior/async_fn.zig created+1676
...@@ -0,0 +1,1676 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;
5const expectEqualStrings = std.testing.expectEqualStrings;
6const expectError = std.testing.expectError;
7
8var global_x: i32 = 1;
9
10test "simple coroutine suspend and resume" {
11 var frame = async simpleAsyncFn();
12 try expect(global_x == 2);
13 resume frame;
14 try expect(global_x == 3);
15 const af: anyframe->void = &frame;
16 resume frame;
17 try expect(global_x == 4);
18}
19fn simpleAsyncFn() void {
20 global_x += 1;
21 suspend {}
22 global_x += 1;
23 suspend {}
24 global_x += 1;
25}
26
27var global_y: i32 = 1;
28
29test "pass parameter to coroutine" {
30 var p = async simpleAsyncFnWithArg(2);
31 try expect(global_y == 3);
32 resume p;
33 try expect(global_y == 5);
34}
35fn simpleAsyncFnWithArg(delta: i32) void {
36 global_y += delta;
37 suspend {}
38 global_y += delta;
39}
40
41test "suspend at end of function" {
42 const S = struct {
43 var x: i32 = 1;
44
45 fn doTheTest() !void {
46 try expect(x == 1);
47 const p = async suspendAtEnd();
48 try expect(x == 2);
49 }
50
51 fn suspendAtEnd() void {
52 x += 1;
53 suspend {}
54 }
55 };
56 try S.doTheTest();
57}
58
59test "local variable in async function" {
60 const S = struct {
61 var x: i32 = 0;
62
63 fn doTheTest() !void {
64 try expect(x == 0);
65 var p = async add(1, 2);
66 try expect(x == 0);
67 resume p;
68 try expect(x == 0);
69 resume p;
70 try expect(x == 0);
71 resume p;
72 try expect(x == 3);
73 }
74
75 fn add(a: i32, b: i32) void {
76 var accum: i32 = 0;
77 suspend {}
78 accum += a;
79 suspend {}
80 accum += b;
81 suspend {}
82 x = accum;
83 }
84 };
85 try S.doTheTest();
86}
87
88test "calling an inferred async function" {
89 const S = struct {
90 var x: i32 = 1;
91 var other_frame: *@Frame(other) = undefined;
92
93 fn doTheTest() !void {
94 _ = async first();
95 try expect(x == 1);
96 resume other_frame.*;
97 try expect(x == 2);
98 }
99
100 fn first() void {
101 other();
102 }
103 fn other() void {
104 other_frame = @frame();
105 suspend {}
106 x += 1;
107 }
108 };
109 try S.doTheTest();
110}
111
112test "@frameSize" {
113 if (builtin.target.cpu.arch == .thumb or builtin.target.cpu.arch == .thumbeb)
114 return error.SkipZigTest;
115
116 const S = struct {
117 fn doTheTest() !void {
118 {
119 var ptr = @ptrCast(fn (i32) callconv(.Async) void, other);
120 const size = @frameSize(ptr);
121 try expect(size == @sizeOf(@Frame(other)));
122 }
123 {
124 var ptr = @ptrCast(fn () callconv(.Async) void, first);
125 const size = @frameSize(ptr);
126 try expect(size == @sizeOf(@Frame(first)));
127 }
128 }
129
130 fn first() void {
131 other(1);
132 }
133 fn other(param: i32) void {
134 var local: i32 = undefined;
135 suspend {}
136 }
137 };
138 try S.doTheTest();
139}
140
141test "coroutine suspend, resume" {
142 const S = struct {
143 var frame: anyframe = undefined;
144
145 fn doTheTest() !void {
146 _ = async amain();
147 seq('d');
148 resume frame;
149 seq('h');
150
151 try expect(std.mem.eql(u8, &points, "abcdefgh"));
152 }
153
154 fn amain() void {
155 seq('a');
156 var f = async testAsyncSeq();
157 seq('c');
158 await f;
159 seq('g');
160 }
161
162 fn testAsyncSeq() void {
163 defer seq('f');
164
165 seq('b');
166 suspend {
167 frame = @frame();
168 }
169 seq('e');
170 }
171 var points = [_]u8{'x'} ** "abcdefgh".len;
172 var index: usize = 0;
173
174 fn seq(c: u8) void {
175 points[index] = c;
176 index += 1;
177 }
178 };
179 try S.doTheTest();
180}
181
182test "coroutine suspend with block" {
183 const p = async testSuspendBlock();
184 try expect(!global_result);
185 resume a_promise;
186 try expect(global_result);
187}
188
189var a_promise: anyframe = undefined;
190var global_result = false;
191fn testSuspendBlock() callconv(.Async) void {
192 suspend {
193 comptime expect(@TypeOf(@frame()) == *@Frame(testSuspendBlock)) catch unreachable;
194 a_promise = @frame();
195 }
196
197 // Test to make sure that @frame() works as advertised (issue #1296)
198 // var our_handle: anyframe = @frame();
199 expect(a_promise == @as(anyframe, @frame())) catch @panic("test failed");
200
201 global_result = true;
202}
203
204var await_a_promise: anyframe = undefined;
205var await_final_result: i32 = 0;
206
207test "coroutine await" {
208 await_seq('a');
209 var p = async await_amain();
210 await_seq('f');
211 resume await_a_promise;
212 await_seq('i');
213 try expect(await_final_result == 1234);
214 try expect(std.mem.eql(u8, &await_points, "abcdefghi"));
215}
216fn await_amain() callconv(.Async) void {
217 await_seq('b');
218 var p = async await_another();
219 await_seq('e');
220 await_final_result = await p;
221 await_seq('h');
222}
223fn await_another() callconv(.Async) i32 {
224 await_seq('c');
225 suspend {
226 await_seq('d');
227 await_a_promise = @frame();
228 }
229 await_seq('g');
230 return 1234;
231}
232
233var await_points = [_]u8{0} ** "abcdefghi".len;
234var await_seq_index: usize = 0;
235
236fn await_seq(c: u8) void {
237 await_points[await_seq_index] = c;
238 await_seq_index += 1;
239}
240
241var early_final_result: i32 = 0;
242
243test "coroutine await early return" {
244 early_seq('a');
245 var p = async early_amain();
246 early_seq('f');
247 try expect(early_final_result == 1234);
248 try expect(std.mem.eql(u8, &early_points, "abcdef"));
249}
250fn early_amain() callconv(.Async) void {
251 early_seq('b');
252 var p = async early_another();
253 early_seq('d');
254 early_final_result = await p;
255 early_seq('e');
256}
257fn early_another() callconv(.Async) i32 {
258 early_seq('c');
259 return 1234;
260}
261
262var early_points = [_]u8{0} ** "abcdef".len;
263var early_seq_index: usize = 0;
264
265fn early_seq(c: u8) void {
266 early_points[early_seq_index] = c;
267 early_seq_index += 1;
268}
269
270test "async function with dot syntax" {
271 const S = struct {
272 var y: i32 = 1;
273 fn foo() callconv(.Async) void {
274 y += 1;
275 suspend {}
276 }
277 };
278 const p = async S.foo();
279 try expect(S.y == 2);
280}
281
282test "async fn pointer in a struct field" {
283 var data: i32 = 1;
284 const Foo = struct {
285 bar: fn (*i32) callconv(.Async) void,
286 };
287 var foo = Foo{ .bar = simpleAsyncFn2 };
288 var bytes: [64]u8 align(16) = undefined;
289 const f = @asyncCall(&bytes, {}, foo.bar, .{&data});
290 comptime try expect(@TypeOf(f) == anyframe->void);
291 try expect(data == 2);
292 resume f;
293 try expect(data == 4);
294 _ = async doTheAwait(f);
295 try expect(data == 4);
296}
297
298fn doTheAwait(f: anyframe->void) void {
299 await f;
300}
301fn simpleAsyncFn2(y: *i32) callconv(.Async) void {
302 defer y.* += 2;
303 y.* += 1;
304 suspend {}
305}
306
307test "@asyncCall with return type" {
308 const Foo = struct {
309 bar: fn () callconv(.Async) i32,
310
311 var global_frame: anyframe = undefined;
312 fn middle() callconv(.Async) i32 {
313 return afunc();
314 }
315
316 fn afunc() i32 {
317 global_frame = @frame();
318 suspend {}
319 return 1234;
320 }
321 };
322 var foo = Foo{ .bar = Foo.middle };
323 var bytes: [150]u8 align(16) = undefined;
324 var aresult: i32 = 0;
325 _ = @asyncCall(&bytes, &aresult, foo.bar, .{});
326 try expect(aresult == 0);
327 resume Foo.global_frame;
328 try expect(aresult == 1234);
329}
330
331test "async fn with inferred error set" {
332 const S = struct {
333 var global_frame: anyframe = undefined;
334
335 fn doTheTest() !void {
336 var frame: [1]@Frame(middle) = undefined;
337 var fn_ptr = middle;
338 var result: @typeInfo(@typeInfo(@TypeOf(fn_ptr)).Fn.return_type.?).ErrorUnion.error_set!void = undefined;
339 _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr, .{});
340 resume global_frame;
341 try std.testing.expectError(error.Fail, result);
342 }
343 fn middle() callconv(.Async) !void {
344 var f = async middle2();
345 return await f;
346 }
347
348 fn middle2() !void {
349 return failing();
350 }
351
352 fn failing() !void {
353 global_frame = @frame();
354 suspend {}
355 return error.Fail;
356 }
357 };
358 try S.doTheTest();
359}
360
361test "error return trace across suspend points - early return" {
362 const p = nonFailing();
363 resume p;
364 const p2 = async printTrace(p);
365}
366
367test "error return trace across suspend points - async return" {
368 const p = nonFailing();
369 const p2 = async printTrace(p);
370 resume p;
371}
372
373fn nonFailing() (anyframe->anyerror!void) {
374 const Static = struct {
375 var frame: @Frame(suspendThenFail) = undefined;
376 };
377 Static.frame = async suspendThenFail();
378 return &Static.frame;
379}
380fn suspendThenFail() callconv(.Async) anyerror!void {
381 suspend {}
382 return error.Fail;
383}
384fn printTrace(p: anyframe->(anyerror!void)) callconv(.Async) void {
385 (await p) catch |e| {
386 std.testing.expect(e == error.Fail) catch @panic("test failure");
387 if (@errorReturnTrace()) |trace| {
388 expect(trace.index == 1) catch @panic("test failure");
389 } else switch (builtin.mode) {
390 .Debug, .ReleaseSafe => @panic("expected return trace"),
391 .ReleaseFast, .ReleaseSmall => {},
392 }
393 };
394}
395
396test "break from suspend" {
397 var my_result: i32 = 1;
398 const p = async testBreakFromSuspend(&my_result);
399 try std.testing.expect(my_result == 2);
400}
401fn testBreakFromSuspend(my_result: *i32) callconv(.Async) void {
402 suspend {
403 resume @frame();
404 }
405 my_result.* += 1;
406 suspend {}
407 my_result.* += 1;
408}
409
410test "heap allocated async function frame" {
411 const S = struct {
412 var x: i32 = 42;
413
414 fn doTheTest() !void {
415 const frame = try std.testing.allocator.create(@Frame(someFunc));
416 defer std.testing.allocator.destroy(frame);
417
418 try expect(x == 42);
419 frame.* = async someFunc();
420 try expect(x == 43);
421 resume frame;
422 try expect(x == 44);
423 }
424
425 fn someFunc() void {
426 x += 1;
427 suspend {}
428 x += 1;
429 }
430 };
431 try S.doTheTest();
432}
433
434test "async function call return value" {
435 const S = struct {
436 var frame: anyframe = undefined;
437 var pt = Point{ .x = 10, .y = 11 };
438
439 fn doTheTest() !void {
440 try expectEqual(pt.x, 10);
441 try expectEqual(pt.y, 11);
442 _ = async first();
443 try expectEqual(pt.x, 10);
444 try expectEqual(pt.y, 11);
445 resume frame;
446 try expectEqual(pt.x, 1);
447 try expectEqual(pt.y, 2);
448 }
449
450 fn first() void {
451 pt = second(1, 2);
452 }
453
454 fn second(x: i32, y: i32) Point {
455 return other(x, y);
456 }
457
458 fn other(x: i32, y: i32) Point {
459 frame = @frame();
460 suspend {}
461 return Point{
462 .x = x,
463 .y = y,
464 };
465 }
466
467 const Point = struct {
468 x: i32,
469 y: i32,
470 };
471 };
472 try S.doTheTest();
473}
474
475test "suspension points inside branching control flow" {
476 const S = struct {
477 var result: i32 = 10;
478
479 fn doTheTest() !void {
480 try expect(10 == result);
481 var frame = async func(true);
482 try expect(10 == result);
483 resume frame;
484 try expect(11 == result);
485 resume frame;
486 try expect(12 == result);
487 resume frame;
488 try expect(13 == result);
489 }
490
491 fn func(b: bool) void {
492 while (b) {
493 suspend {}
494 result += 1;
495 }
496 }
497 };
498 try S.doTheTest();
499}
500
501test "call async function which has struct return type" {
502 const S = struct {
503 var frame: anyframe = undefined;
504
505 fn doTheTest() void {
506 _ = async atest();
507 resume frame;
508 }
509
510 fn atest() void {
511 const result = func();
512 expect(result.x == 5) catch @panic("test failed");
513 expect(result.y == 6) catch @panic("test failed");
514 }
515
516 const Point = struct {
517 x: usize,
518 y: usize,
519 };
520
521 fn func() Point {
522 suspend {
523 frame = @frame();
524 }
525 return Point{
526 .x = 5,
527 .y = 6,
528 };
529 }
530 };
531 S.doTheTest();
532}
533
534test "pass string literal to async function" {
535 const S = struct {
536 var frame: anyframe = undefined;
537 var ok: bool = false;
538
539 fn doTheTest() !void {
540 _ = async hello("hello");
541 resume frame;
542 try expect(ok);
543 }
544
545 fn hello(msg: []const u8) void {
546 frame = @frame();
547 suspend {}
548 expectEqualStrings("hello", msg) catch @panic("test failed");
549 ok = true;
550 }
551 };
552 try S.doTheTest();
553}
554
555test "await inside an errdefer" {
556 const S = struct {
557 var frame: anyframe = undefined;
558
559 fn doTheTest() !void {
560 _ = async amainWrap();
561 resume frame;
562 }
563
564 fn amainWrap() !void {
565 var foo = async func();
566 errdefer await foo;
567 return error.Bad;
568 }
569
570 fn func() void {
571 frame = @frame();
572 suspend {}
573 }
574 };
575 try S.doTheTest();
576}
577
578test "try in an async function with error union and non-zero-bit payload" {
579 const S = struct {
580 var frame: anyframe = undefined;
581 var ok = false;
582
583 fn doTheTest() !void {
584 _ = async amain();
585 resume frame;
586 try expect(ok);
587 }
588
589 fn amain() void {
590 std.testing.expectError(error.Bad, theProblem()) catch @panic("test failed");
591 ok = true;
592 }
593
594 fn theProblem() ![]u8 {
595 frame = @frame();
596 suspend {}
597 const result = try other();
598 return result;
599 }
600
601 fn other() ![]u8 {
602 return error.Bad;
603 }
604 };
605 try S.doTheTest();
606}
607
608test "returning a const error from async function" {
609 const S = struct {
610 var frame: anyframe = undefined;
611 var ok = false;
612
613 fn doTheTest() !void {
614 _ = async amain();
615 resume frame;
616 try expect(ok);
617 }
618
619 fn amain() !void {
620 var download_frame = async fetchUrl(10, "a string");
621 const download_text = try await download_frame;
622
623 @panic("should not get here");
624 }
625
626 fn fetchUrl(unused: i32, url: []const u8) ![]u8 {
627 frame = @frame();
628 suspend {}
629 ok = true;
630 return error.OutOfMemory;
631 }
632 };
633 try S.doTheTest();
634}
635
636test "async/await typical usage" {
637 inline for ([_]bool{ false, true }) |b1| {
638 inline for ([_]bool{ false, true }) |b2| {
639 inline for ([_]bool{ false, true }) |b3| {
640 inline for ([_]bool{ false, true }) |b4| {
641 testAsyncAwaitTypicalUsage(b1, b2, b3, b4).doTheTest();
642 }
643 }
644 }
645 }
646}
647
648fn testAsyncAwaitTypicalUsage(
649 comptime simulate_fail_download: bool,
650 comptime simulate_fail_file: bool,
651 comptime suspend_download: bool,
652 comptime suspend_file: bool,
653) type {
654 return struct {
655 fn doTheTest() void {
656 _ = async amainWrap();
657 if (suspend_file) {
658 resume global_file_frame;
659 }
660 if (suspend_download) {
661 resume global_download_frame;
662 }
663 }
664 fn amainWrap() void {
665 if (amain()) |_| {
666 expect(!simulate_fail_download) catch @panic("test failure");
667 expect(!simulate_fail_file) catch @panic("test failure");
668 } else |e| switch (e) {
669 error.NoResponse => expect(simulate_fail_download) catch @panic("test failure"),
670 error.FileNotFound => expect(simulate_fail_file) catch @panic("test failure"),
671 else => @panic("test failure"),
672 }
673 }
674
675 fn amain() !void {
676 const allocator = std.testing.allocator;
677 var download_frame = async fetchUrl(allocator, "https://example.com/");
678 var download_awaited = false;
679 errdefer if (!download_awaited) {
680 if (await download_frame) |x| allocator.free(x) else |_| {}
681 };
682
683 var file_frame = async readFile(allocator, "something.txt");
684 var file_awaited = false;
685 errdefer if (!file_awaited) {
686 if (await file_frame) |x| allocator.free(x) else |_| {}
687 };
688
689 download_awaited = true;
690 const download_text = try await download_frame;
691 defer allocator.free(download_text);
692
693 file_awaited = true;
694 const file_text = try await file_frame;
695 defer allocator.free(file_text);
696
697 try expect(std.mem.eql(u8, "expected download text", download_text));
698 try expect(std.mem.eql(u8, "expected file text", file_text));
699 }
700
701 var global_download_frame: anyframe = undefined;
702 fn fetchUrl(allocator: *std.mem.Allocator, url: []const u8) anyerror![]u8 {
703 const result = try std.mem.dupe(allocator, u8, "expected download text");
704 errdefer allocator.free(result);
705 if (suspend_download) {
706 suspend {
707 global_download_frame = @frame();
708 }
709 }
710 if (simulate_fail_download) return error.NoResponse;
711 return result;
712 }
713
714 var global_file_frame: anyframe = undefined;
715 fn readFile(allocator: *std.mem.Allocator, filename: []const u8) anyerror![]u8 {
716 const result = try std.mem.dupe(allocator, u8, "expected file text");
717 errdefer allocator.free(result);
718 if (suspend_file) {
719 suspend {
720 global_file_frame = @frame();
721 }
722 }
723 if (simulate_fail_file) return error.FileNotFound;
724 return result;
725 }
726 };
727}
728
729test "alignment of local variables in async functions" {
730 const S = struct {
731 fn doTheTest() !void {
732 var y: u8 = 123;
733 var x: u8 align(128) = 1;
734 try expect(@ptrToInt(&x) % 128 == 0);
735 }
736 };
737 try S.doTheTest();
738}
739
740test "no reason to resolve frame still works" {
741 _ = async simpleNothing();
742}
743fn simpleNothing() void {
744 var x: i32 = 1234;
745}
746
747test "async call a generic function" {
748 const S = struct {
749 fn doTheTest() !void {
750 var f = async func(i32, 2);
751 const result = await f;
752 try expect(result == 3);
753 }
754
755 fn func(comptime T: type, inc: T) T {
756 var x: T = 1;
757 suspend {
758 resume @frame();
759 }
760 x += inc;
761 return x;
762 }
763 };
764 _ = async S.doTheTest();
765}
766
767test "return from suspend block" {
768 const S = struct {
769 fn doTheTest() !void {
770 expect(func() == 1234) catch @panic("test failure");
771 }
772 fn func() i32 {
773 suspend {
774 return 1234;
775 }
776 }
777 };
778 _ = async S.doTheTest();
779}
780
781test "struct parameter to async function is copied to the frame" {
782 const S = struct {
783 const Point = struct {
784 x: i32,
785 y: i32,
786 };
787
788 var frame: anyframe = undefined;
789
790 fn doTheTest() void {
791 _ = async atest();
792 resume frame;
793 }
794
795 fn atest() void {
796 var f: @Frame(foo) = undefined;
797 bar(&f);
798 clobberStack(10);
799 }
800
801 fn clobberStack(x: i32) void {
802 if (x == 0) return;
803 clobberStack(x - 1);
804 var y: i32 = x;
805 }
806
807 fn bar(f: *@Frame(foo)) void {
808 var pt = Point{ .x = 1, .y = 2 };
809 f.* = async foo(pt);
810 var result = await f;
811 expect(result == 1) catch @panic("test failure");
812 }
813
814 fn foo(point: Point) i32 {
815 suspend {
816 frame = @frame();
817 }
818 return point.x;
819 }
820 };
821 S.doTheTest();
822}
823
824test "cast fn to async fn when it is inferred to be async" {
825 const S = struct {
826 var frame: anyframe = undefined;
827 var ok = false;
828
829 fn doTheTest() void {
830 var ptr: fn () callconv(.Async) i32 = undefined;
831 ptr = func;
832 var buf: [100]u8 align(16) = undefined;
833 var result: i32 = undefined;
834 const f = @asyncCall(&buf, &result, ptr, .{});
835 _ = await f;
836 expect(result == 1234) catch @panic("test failure");
837 ok = true;
838 }
839
840 fn func() i32 {
841 suspend {
842 frame = @frame();
843 }
844 return 1234;
845 }
846 };
847 _ = async S.doTheTest();
848 resume S.frame;
849 try expect(S.ok);
850}
851
852test "cast fn to async fn when it is inferred to be async, awaited directly" {
853 const S = struct {
854 var frame: anyframe = undefined;
855 var ok = false;
856
857 fn doTheTest() void {
858 var ptr: fn () callconv(.Async) i32 = undefined;
859 ptr = func;
860 var buf: [100]u8 align(16) = undefined;
861 var result: i32 = undefined;
862 _ = await @asyncCall(&buf, &result, ptr, .{});
863 expect(result == 1234) catch @panic("test failure");
864 ok = true;
865 }
866
867 fn func() i32 {
868 suspend {
869 frame = @frame();
870 }
871 return 1234;
872 }
873 };
874 _ = async S.doTheTest();
875 resume S.frame;
876 try expect(S.ok);
877}
878
879test "await does not force async if callee is blocking" {
880 const S = struct {
881 fn simple() i32 {
882 return 1234;
883 }
884 };
885 var x = async S.simple();
886 try expect(await x == 1234);
887}
888
889test "recursive async function" {
890 try expect(recursiveAsyncFunctionTest(false).doTheTest() == 55);
891 try expect(recursiveAsyncFunctionTest(true).doTheTest() == 55);
892}
893
894fn recursiveAsyncFunctionTest(comptime suspending_implementation: bool) type {
895 return struct {
896 fn fib(allocator: *std.mem.Allocator, x: u32) error{OutOfMemory}!u32 {
897 if (x <= 1) return x;
898
899 if (suspending_implementation) {
900 suspend {
901 resume @frame();
902 }
903 }
904
905 const f1 = try allocator.create(@Frame(fib));
906 defer allocator.destroy(f1);
907
908 const f2 = try allocator.create(@Frame(fib));
909 defer allocator.destroy(f2);
910
911 f1.* = async fib(allocator, x - 1);
912 var f1_awaited = false;
913 errdefer if (!f1_awaited) {
914 _ = await f1;
915 };
916
917 f2.* = async fib(allocator, x - 2);
918 var f2_awaited = false;
919 errdefer if (!f2_awaited) {
920 _ = await f2;
921 };
922
923 var sum: u32 = 0;
924
925 f1_awaited = true;
926 sum += try await f1;
927
928 f2_awaited = true;
929 sum += try await f2;
930
931 return sum;
932 }
933
934 fn doTheTest() u32 {
935 if (suspending_implementation) {
936 var result: u32 = undefined;
937 _ = async amain(&result);
938 return result;
939 } else {
940 return fib(std.testing.allocator, 10) catch unreachable;
941 }
942 }
943
944 fn amain(result: *u32) void {
945 var x = async fib(std.testing.allocator, 10);
946 result.* = (await x) catch unreachable;
947 }
948 };
949}
950
951test "@asyncCall with comptime-known function, but not awaited directly" {
952 const S = struct {
953 var global_frame: anyframe = undefined;
954
955 fn doTheTest() !void {
956 var frame: [1]@Frame(middle) = undefined;
957 var result: @typeInfo(@typeInfo(@TypeOf(middle)).Fn.return_type.?).ErrorUnion.error_set!void = undefined;
958 _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle, .{});
959 resume global_frame;
960 try std.testing.expectError(error.Fail, result);
961 }
962 fn middle() callconv(.Async) !void {
963 var f = async middle2();
964 return await f;
965 }
966
967 fn middle2() !void {
968 return failing();
969 }
970
971 fn failing() !void {
972 global_frame = @frame();
973 suspend {}
974 return error.Fail;
975 }
976 };
977 try S.doTheTest();
978}
979
980test "@asyncCall with actual frame instead of byte buffer" {
981 const S = struct {
982 fn func() i32 {
983 suspend {}
984 return 1234;
985 }
986 };
987 var frame: @Frame(S.func) = undefined;
988 var result: i32 = undefined;
989 const ptr = @asyncCall(&frame, &result, S.func, .{});
990 resume ptr;
991 try expect(result == 1234);
992}
993
994test "@asyncCall using the result location inside the frame" {
995 const S = struct {
996 fn simple2(y: *i32) callconv(.Async) i32 {
997 defer y.* += 2;
998 y.* += 1;
999 suspend {}
1000 return 1234;
1001 }
1002 fn getAnswer(f: anyframe->i32, out: *i32) void {
1003 out.* = await f;
1004 }
1005 };
1006 var data: i32 = 1;
1007 const Foo = struct {
1008 bar: fn (*i32) callconv(.Async) i32,
1009 };
1010 var foo = Foo{ .bar = S.simple2 };
1011 var bytes: [64]u8 align(16) = undefined;
1012 const f = @asyncCall(&bytes, {}, foo.bar, .{&data});
1013 comptime try expect(@TypeOf(f) == anyframe->i32);
1014 try expect(data == 2);
1015 resume f;
1016 try expect(data == 4);
1017 _ = async S.getAnswer(f, &data);
1018 try expect(data == 1234);
1019}
1020
1021test "@TypeOf an async function call of generic fn with error union type" {
1022 const S = struct {
1023 fn func(comptime x: anytype) anyerror!i32 {
1024 const T = @TypeOf(async func(x));
1025 comptime try expect(T == @typeInfo(@TypeOf(@frame())).Pointer.child);
1026 return undefined;
1027 }
1028 };
1029 _ = async S.func(i32);
1030}
1031
1032test "using @TypeOf on a generic function call" {
1033 const S = struct {
1034 var global_frame: anyframe = undefined;
1035 var global_ok = false;
1036
1037 var buf: [100]u8 align(16) = undefined;
1038
1039 fn amain(x: anytype) void {
1040 if (x == 0) {
1041 global_ok = true;
1042 return;
1043 }
1044 suspend {
1045 global_frame = @frame();
1046 }
1047 const F = @TypeOf(async amain(x - 1));
1048 const frame = @intToPtr(*F, @ptrToInt(&buf));
1049 return await @asyncCall(frame, {}, amain, .{x - 1});
1050 }
1051 };
1052 _ = async S.amain(@as(u32, 1));
1053 resume S.global_frame;
1054 try expect(S.global_ok);
1055}
1056
1057test "recursive call of await @asyncCall with struct return type" {
1058 const S = struct {
1059 var global_frame: anyframe = undefined;
1060 var global_ok = false;
1061
1062 var buf: [100]u8 align(16) = undefined;
1063
1064 fn amain(x: anytype) Foo {
1065 if (x == 0) {
1066 global_ok = true;
1067 return Foo{ .x = 1, .y = 2, .z = 3 };
1068 }
1069 suspend {
1070 global_frame = @frame();
1071 }
1072 const F = @TypeOf(async amain(x - 1));
1073 const frame = @intToPtr(*F, @ptrToInt(&buf));
1074 return await @asyncCall(frame, {}, amain, .{x - 1});
1075 }
1076
1077 const Foo = struct {
1078 x: u64,
1079 y: u64,
1080 z: u64,
1081 };
1082 };
1083 var res: S.Foo = undefined;
1084 var frame: @TypeOf(async S.amain(@as(u32, 1))) = undefined;
1085 _ = @asyncCall(&frame, &res, S.amain, .{@as(u32, 1)});
1086 resume S.global_frame;
1087 try expect(S.global_ok);
1088 try expect(res.x == 1);
1089 try expect(res.y == 2);
1090 try expect(res.z == 3);
1091}
1092
1093test "nosuspend function call" {
1094 const S = struct {
1095 fn doTheTest() !void {
1096 const result = nosuspend add(50, 100);
1097 try expect(result == 150);
1098 }
1099 fn add(a: i32, b: i32) i32 {
1100 if (a > 100) {
1101 suspend {}
1102 }
1103 return a + b;
1104 }
1105 };
1106 try S.doTheTest();
1107}
1108
1109test "await used in expression and awaiting fn with no suspend but async calling convention" {
1110 const S = struct {
1111 fn atest() void {
1112 var f1 = async add(1, 2);
1113 var f2 = async add(3, 4);
1114
1115 const sum = (await f1) + (await f2);
1116 expect(sum == 10) catch @panic("test failure");
1117 }
1118 fn add(a: i32, b: i32) callconv(.Async) i32 {
1119 return a + b;
1120 }
1121 };
1122 _ = async S.atest();
1123}
1124
1125test "await used in expression after a fn call" {
1126 const S = struct {
1127 fn atest() void {
1128 var f1 = async add(3, 4);
1129 var sum: i32 = 0;
1130 sum = foo() + await f1;
1131 expect(sum == 8) catch @panic("test failure");
1132 }
1133 fn add(a: i32, b: i32) callconv(.Async) i32 {
1134 return a + b;
1135 }
1136 fn foo() i32 {
1137 return 1;
1138 }
1139 };
1140 _ = async S.atest();
1141}
1142
1143test "async fn call used in expression after a fn call" {
1144 const S = struct {
1145 fn atest() void {
1146 var sum: i32 = 0;
1147 sum = foo() + add(3, 4);
1148 expect(sum == 8) catch @panic("test failure");
1149 }
1150 fn add(a: i32, b: i32) callconv(.Async) i32 {
1151 return a + b;
1152 }
1153 fn foo() i32 {
1154 return 1;
1155 }
1156 };
1157 _ = async S.atest();
1158}
1159
1160test "suspend in for loop" {
1161 const S = struct {
1162 var global_frame: ?anyframe = null;
1163
1164 fn doTheTest() void {
1165 _ = async atest();
1166 while (global_frame) |f| resume f;
1167 }
1168
1169 fn atest() void {
1170 expect(func(&[_]u8{ 1, 2, 3 }) == 6) catch @panic("test failure");
1171 }
1172 fn func(stuff: []const u8) u32 {
1173 global_frame = @frame();
1174 var sum: u32 = 0;
1175 for (stuff) |x| {
1176 suspend {}
1177 sum += x;
1178 }
1179 global_frame = null;
1180 return sum;
1181 }
1182 };
1183 S.doTheTest();
1184}
1185
1186test "suspend in while loop" {
1187 const S = struct {
1188 var global_frame: ?anyframe = null;
1189
1190 fn doTheTest() void {
1191 _ = async atest();
1192 while (global_frame) |f| resume f;
1193 }
1194
1195 fn atest() void {
1196 expect(optional(6) == 6) catch @panic("test failure");
1197 expect(errunion(6) == 6) catch @panic("test failure");
1198 }
1199 fn optional(stuff: ?u32) u32 {
1200 global_frame = @frame();
1201 defer global_frame = null;
1202 while (stuff) |val| {
1203 suspend {}
1204 return val;
1205 }
1206 return 0;
1207 }
1208 fn errunion(stuff: anyerror!u32) u32 {
1209 global_frame = @frame();
1210 defer global_frame = null;
1211 while (stuff) |val| {
1212 suspend {}
1213 return val;
1214 } else |err| {
1215 return 0;
1216 }
1217 }
1218 };
1219 S.doTheTest();
1220}
1221
1222test "correctly spill when returning the error union result of another async fn" {
1223 const S = struct {
1224 var global_frame: anyframe = undefined;
1225
1226 fn doTheTest() !void {
1227 expect((atest() catch unreachable) == 1234) catch @panic("test failure");
1228 }
1229
1230 fn atest() !i32 {
1231 return fallible1();
1232 }
1233
1234 fn fallible1() anyerror!i32 {
1235 suspend {
1236 global_frame = @frame();
1237 }
1238 return 1234;
1239 }
1240 };
1241 _ = async S.doTheTest();
1242 resume S.global_frame;
1243}
1244
1245test "spill target expr in a for loop" {
1246 const S = struct {
1247 var global_frame: anyframe = undefined;
1248
1249 fn doTheTest() !void {
1250 var foo = Foo{
1251 .slice = &[_]i32{ 1, 2 },
1252 };
1253 expect(atest(&foo) == 3) catch @panic("test failure");
1254 }
1255
1256 const Foo = struct {
1257 slice: []const i32,
1258 };
1259
1260 fn atest(foo: *Foo) i32 {
1261 var sum: i32 = 0;
1262 for (foo.slice) |x| {
1263 suspend {
1264 global_frame = @frame();
1265 }
1266 sum += x;
1267 }
1268 return sum;
1269 }
1270 };
1271 _ = async S.doTheTest();
1272 resume S.global_frame;
1273 resume S.global_frame;
1274}
1275
1276test "spill target expr in a for loop, with a var decl in the loop body" {
1277 const S = struct {
1278 var global_frame: anyframe = undefined;
1279
1280 fn doTheTest() !void {
1281 var foo = Foo{
1282 .slice = &[_]i32{ 1, 2 },
1283 };
1284 expect(atest(&foo) == 3) catch @panic("test failure");
1285 }
1286
1287 const Foo = struct {
1288 slice: []const i32,
1289 };
1290
1291 fn atest(foo: *Foo) i32 {
1292 var sum: i32 = 0;
1293 for (foo.slice) |x| {
1294 // Previously this var decl would prevent spills. This test makes sure
1295 // the for loop spills still happen even though there is a VarDecl in scope
1296 // before the suspend.
1297 var anything = true;
1298 _ = anything;
1299 suspend {
1300 global_frame = @frame();
1301 }
1302 sum += x;
1303 }
1304 return sum;
1305 }
1306 };
1307 _ = async S.doTheTest();
1308 resume S.global_frame;
1309 resume S.global_frame;
1310}
1311
1312test "async call with @call" {
1313 const S = struct {
1314 var global_frame: anyframe = undefined;
1315 fn doTheTest() void {
1316 _ = @call(.{ .modifier = .async_kw }, atest, .{});
1317 resume global_frame;
1318 }
1319 fn atest() void {
1320 var frame = @call(.{ .modifier = .async_kw }, afoo, .{});
1321 const res = await frame;
1322 expect(res == 42) catch @panic("test failure");
1323 }
1324 fn afoo() i32 {
1325 suspend {
1326 global_frame = @frame();
1327 }
1328 return 42;
1329 }
1330 };
1331 S.doTheTest();
1332}
1333
1334test "async function passed 0-bit arg after non-0-bit arg" {
1335 const S = struct {
1336 var global_frame: anyframe = undefined;
1337 var global_int: i32 = 0;
1338
1339 fn foo() void {
1340 bar(1, .{}) catch unreachable;
1341 }
1342
1343 fn bar(x: i32, args: anytype) anyerror!void {
1344 global_frame = @frame();
1345 suspend {}
1346 global_int = x;
1347 }
1348 };
1349 _ = async S.foo();
1350 resume S.global_frame;
1351 try expect(S.global_int == 1);
1352}
1353
1354test "async function passed align(16) arg after align(8) arg" {
1355 const S = struct {
1356 var global_frame: anyframe = undefined;
1357 var global_int: u128 = 0;
1358
1359 fn foo() void {
1360 var a: u128 = 99;
1361 bar(10, .{a}) catch unreachable;
1362 }
1363
1364 fn bar(x: u64, args: anytype) anyerror!void {
1365 try expect(x == 10);
1366 global_frame = @frame();
1367 suspend {}
1368 global_int = args[0];
1369 }
1370 };
1371 _ = async S.foo();
1372 resume S.global_frame;
1373 try expect(S.global_int == 99);
1374}
1375
1376test "async function call resolves target fn frame, comptime func" {
1377 const S = struct {
1378 var global_frame: anyframe = undefined;
1379 var global_int: i32 = 9;
1380
1381 fn foo() anyerror!void {
1382 const stack_size = 1000;
1383 var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
1384 return await @asyncCall(&stack_frame, {}, bar, .{});
1385 }
1386
1387 fn bar() anyerror!void {
1388 global_frame = @frame();
1389 suspend {}
1390 global_int += 1;
1391 }
1392 };
1393 _ = async S.foo();
1394 resume S.global_frame;
1395 try expect(S.global_int == 10);
1396}
1397
1398test "async function call resolves target fn frame, runtime func" {
1399 const S = struct {
1400 var global_frame: anyframe = undefined;
1401 var global_int: i32 = 9;
1402
1403 fn foo() anyerror!void {
1404 const stack_size = 1000;
1405 var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
1406 var func: fn () callconv(.Async) anyerror!void = bar;
1407 return await @asyncCall(&stack_frame, {}, func, .{});
1408 }
1409
1410 fn bar() anyerror!void {
1411 global_frame = @frame();
1412 suspend {}
1413 global_int += 1;
1414 }
1415 };
1416 _ = async S.foo();
1417 resume S.global_frame;
1418 try expect(S.global_int == 10);
1419}
1420
1421test "properly spill optional payload capture value" {
1422 const S = struct {
1423 var global_frame: anyframe = undefined;
1424 var global_int: usize = 2;
1425
1426 fn foo() void {
1427 var opt: ?usize = 1234;
1428 if (opt) |x| {
1429 bar();
1430 global_int += x;
1431 }
1432 }
1433
1434 fn bar() void {
1435 global_frame = @frame();
1436 suspend {}
1437 global_int += 1;
1438 }
1439 };
1440 _ = async S.foo();
1441 resume S.global_frame;
1442 try expect(S.global_int == 1237);
1443}
1444
1445test "handle defer interfering with return value spill" {
1446 const S = struct {
1447 var global_frame1: anyframe = undefined;
1448 var global_frame2: anyframe = undefined;
1449 var finished = false;
1450 var baz_happened = false;
1451
1452 fn doTheTest() !void {
1453 _ = async testFoo();
1454 resume global_frame1;
1455 resume global_frame2;
1456 try expect(baz_happened);
1457 try expect(finished);
1458 }
1459
1460 fn testFoo() void {
1461 expectError(error.Bad, foo()) catch @panic("test failure");
1462 finished = true;
1463 }
1464
1465 fn foo() anyerror!void {
1466 defer baz();
1467 return bar() catch |err| return err;
1468 }
1469
1470 fn bar() anyerror!void {
1471 global_frame1 = @frame();
1472 suspend {}
1473 return error.Bad;
1474 }
1475
1476 fn baz() void {
1477 global_frame2 = @frame();
1478 suspend {}
1479 baz_happened = true;
1480 }
1481 };
1482 try S.doTheTest();
1483}
1484
1485test "take address of temporary async frame" {
1486 const S = struct {
1487 var global_frame: anyframe = undefined;
1488 var finished = false;
1489
1490 fn doTheTest() !void {
1491 _ = async asyncDoTheTest();
1492 resume global_frame;
1493 try expect(finished);
1494 }
1495
1496 fn asyncDoTheTest() void {
1497 expect(finishIt(&async foo(10)) == 1245) catch @panic("test failure");
1498 finished = true;
1499 }
1500
1501 fn foo(arg: i32) i32 {
1502 global_frame = @frame();
1503 suspend {}
1504 return arg + 1234;
1505 }
1506
1507 fn finishIt(frame: anyframe->i32) i32 {
1508 return (await frame) + 1;
1509 }
1510 };
1511 try S.doTheTest();
1512}
1513
1514test "nosuspend await" {
1515 const S = struct {
1516 var finished = false;
1517
1518 fn doTheTest() !void {
1519 var frame = async foo(false);
1520 try expect(nosuspend await frame == 42);
1521 finished = true;
1522 }
1523
1524 fn foo(want_suspend: bool) i32 {
1525 if (want_suspend) {
1526 suspend {}
1527 }
1528 return 42;
1529 }
1530 };
1531 try S.doTheTest();
1532 try expect(S.finished);
1533}
1534
1535test "nosuspend on function calls" {
1536 const S0 = struct {
1537 b: i32 = 42,
1538 };
1539 const S1 = struct {
1540 fn c() S0 {
1541 return S0{};
1542 }
1543 fn d() !S0 {
1544 return S0{};
1545 }
1546 };
1547 try expectEqual(@as(i32, 42), nosuspend S1.c().b);
1548 try expectEqual(@as(i32, 42), (try nosuspend S1.d()).b);
1549}
1550
1551test "nosuspend on async function calls" {
1552 const S0 = struct {
1553 b: i32 = 42,
1554 };
1555 const S1 = struct {
1556 fn c() S0 {
1557 return S0{};
1558 }
1559 fn d() !S0 {
1560 return S0{};
1561 }
1562 };
1563 var frame_c = nosuspend async S1.c();
1564 try expectEqual(@as(i32, 42), (await frame_c).b);
1565 var frame_d = nosuspend async S1.d();
1566 try expectEqual(@as(i32, 42), (try await frame_d).b);
1567}
1568
1569// test "resume nosuspend async function calls" {
1570// const S0 = struct {
1571// b: i32 = 42,
1572// };
1573// const S1 = struct {
1574// fn c() S0 {
1575// suspend {}
1576// return S0{};
1577// }
1578// fn d() !S0 {
1579// suspend {}
1580// return S0{};
1581// }
1582// };
1583// var frame_c = nosuspend async S1.c();
1584// resume frame_c;
1585// try expectEqual(@as(i32, 42), (await frame_c).b);
1586// var frame_d = nosuspend async S1.d();
1587// resume frame_d;
1588// try expectEqual(@as(i32, 42), (try await frame_d).b);
1589// }
1590
1591test "nosuspend resume async function calls" {
1592 const S0 = struct {
1593 b: i32 = 42,
1594 };
1595 const S1 = struct {
1596 fn c() S0 {
1597 suspend {}
1598 return S0{};
1599 }
1600 fn d() !S0 {
1601 suspend {}
1602 return S0{};
1603 }
1604 };
1605 var frame_c = async S1.c();
1606 nosuspend resume frame_c;
1607 try expectEqual(@as(i32, 42), (await frame_c).b);
1608 var frame_d = async S1.d();
1609 nosuspend resume frame_d;
1610 try expectEqual(@as(i32, 42), (try await frame_d).b);
1611}
1612
1613test "avoid forcing frame alignment resolution implicit cast to *c_void" {
1614 const S = struct {
1615 var x: ?*c_void = null;
1616
1617 fn foo() bool {
1618 suspend {
1619 x = @frame();
1620 }
1621 return true;
1622 }
1623 };
1624 var frame = async S.foo();
1625 resume @ptrCast(anyframe->bool, @alignCast(@alignOf(@Frame(S.foo)), S.x));
1626 try expect(nosuspend await frame);
1627}
1628
1629test "@asyncCall with pass-by-value arguments" {
1630 const F0: u64 = 0xbeefbeefbeefbeef;
1631 const F1: u64 = 0xf00df00df00df00d;
1632 const F2: u64 = 0xcafecafecafecafe;
1633
1634 const S = struct {
1635 pub const ST = struct { f0: usize, f1: usize };
1636 pub const AT = [5]u8;
1637
1638 pub fn f(_fill0: u64, s: ST, _fill1: u64, a: AT, _fill2: u64) callconv(.Async) void {
1639 // Check that the array and struct arguments passed by value don't
1640 // end up overflowing the adjacent fields in the frame structure.
1641 expectEqual(F0, _fill0) catch @panic("test failure");
1642 expectEqual(F1, _fill1) catch @panic("test failure");
1643 expectEqual(F2, _fill2) catch @panic("test failure");
1644 }
1645 };
1646
1647 var buffer: [1024]u8 align(@alignOf(@Frame(S.f))) = undefined;
1648 // The function pointer must not be comptime-known.
1649 var t = S.f;
1650 var frame_ptr = @asyncCall(&buffer, {}, t, .{
1651 F0,
1652 .{ .f0 = 1, .f1 = 2 },
1653 F1,
1654 [_]u8{ 1, 2, 3, 4, 5 },
1655 F2,
1656 });
1657}
1658
1659test "@asyncCall with arguments having non-standard alignment" {
1660 const F0: u64 = 0xbeefbeef;
1661 const F1: u64 = 0xf00df00df00df00d;
1662
1663 const S = struct {
1664 pub fn f(_fill0: u32, s: struct { x: u64 align(16) }, _fill1: u64) callconv(.Async) void {
1665 // The compiler inserts extra alignment for s, check that the
1666 // generated code picks the right slot for fill1.
1667 expectEqual(F0, _fill0) catch @panic("test failure");
1668 expectEqual(F1, _fill1) catch @panic("test failure");
1669 }
1670 };
1671
1672 var buffer: [1024]u8 align(@alignOf(@Frame(S.f))) = undefined;
1673 // The function pointer must not be comptime-known.
1674 var t = S.f;
1675 var frame_ptr = @asyncCall(&buffer, {}, t, .{ F0, undefined, F1 });
1676}
test/behavior/atomics.zig created+219
...@@ -0,0 +1,219 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const builtin = @import("builtin");
5
6test "cmpxchg" {
7 try testCmpxchg();
8 comptime try testCmpxchg();
9}
10
11fn testCmpxchg() !void {
12 var x: i32 = 1234;
13 if (@cmpxchgWeak(i32, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
14 try expect(x1 == 1234);
15 } else {
16 @panic("cmpxchg should have failed");
17 }
18
19 while (@cmpxchgWeak(i32, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
20 try expect(x1 == 1234);
21 }
22 try expect(x == 5678);
23
24 try expect(@cmpxchgStrong(i32, &x, 5678, 42, .SeqCst, .SeqCst) == null);
25 try expect(x == 42);
26}
27
28test "fence" {
29 var x: i32 = 1234;
30 @fence(.SeqCst);
31 x = 5678;
32}
33
34test "atomicrmw and atomicload" {
35 var data: u8 = 200;
36 try testAtomicRmw(&data);
37 try expect(data == 42);
38 try testAtomicLoad(&data);
39}
40
41fn testAtomicRmw(ptr: *u8) !void {
42 const prev_value = @atomicRmw(u8, ptr, .Xchg, 42, .SeqCst);
43 try expect(prev_value == 200);
44 comptime {
45 var x: i32 = 1234;
46 const y: i32 = 12345;
47 try expect(@atomicLoad(i32, &x, .SeqCst) == 1234);
48 try expect(@atomicLoad(i32, &y, .SeqCst) == 12345);
49 }
50}
51
52fn testAtomicLoad(ptr: *u8) !void {
53 const x = @atomicLoad(u8, ptr, .SeqCst);
54 try expect(x == 42);
55}
56
57test "cmpxchg with ptr" {
58 var data1: i32 = 1234;
59 var data2: i32 = 5678;
60 var data3: i32 = 9101;
61 var x: *i32 = &data1;
62 if (@cmpxchgWeak(*i32, &x, &data2, &data3, .SeqCst, .SeqCst)) |x1| {
63 try expect(x1 == &data1);
64 } else {
65 @panic("cmpxchg should have failed");
66 }
67
68 while (@cmpxchgWeak(*i32, &x, &data1, &data3, .SeqCst, .SeqCst)) |x1| {
69 try expect(x1 == &data1);
70 }
71 try expect(x == &data3);
72
73 try expect(@cmpxchgStrong(*i32, &x, &data3, &data2, .SeqCst, .SeqCst) == null);
74 try expect(x == &data2);
75}
76
77// TODO this test is disabled until this issue is resolved:
78// https://github.com/ziglang/zig/issues/2883
79// otherwise cross compiling will result in:
80// lld: error: undefined symbol: __sync_val_compare_and_swap_16
81//test "128-bit cmpxchg" {
82// var x: u128 align(16) = 1234; // TODO: https://github.com/ziglang/zig/issues/2987
83// if (@cmpxchgWeak(u128, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
84// try expect(x1 == 1234);
85// } else {
86// @panic("cmpxchg should have failed");
87// }
88//
89// while (@cmpxchgWeak(u128, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
90// try expect(x1 == 1234);
91// }
92// try expect(x == 5678);
93//
94// try expect(@cmpxchgStrong(u128, &x, 5678, 42, .SeqCst, .SeqCst) == null);
95// try expect(x == 42);
96//}
97
98test "cmpxchg with ignored result" {
99 var x: i32 = 1234;
100 var ptr = &x;
101
102 _ = @cmpxchgStrong(i32, &x, 1234, 5678, .Monotonic, .Monotonic);
103
104 try expectEqual(@as(i32, 5678), x);
105}
106
107var a_global_variable = @as(u32, 1234);
108
109test "cmpxchg on a global variable" {
110 _ = @cmpxchgWeak(u32, &a_global_variable, 1234, 42, .Acquire, .Monotonic);
111 try expectEqual(@as(u32, 42), a_global_variable);
112}
113
114test "atomic load and rmw with enum" {
115 const Value = enum(u8) {
116 a,
117 b,
118 c,
119 };
120 var x = Value.a;
121
122 try expect(@atomicLoad(Value, &x, .SeqCst) != .b);
123
124 _ = @atomicRmw(Value, &x, .Xchg, .c, .SeqCst);
125 try expect(@atomicLoad(Value, &x, .SeqCst) == .c);
126 try expect(@atomicLoad(Value, &x, .SeqCst) != .a);
127 try expect(@atomicLoad(Value, &x, .SeqCst) != .b);
128}
129
130test "atomic store" {
131 var x: u32 = 0;
132 @atomicStore(u32, &x, 1, .SeqCst);
133 try expect(@atomicLoad(u32, &x, .SeqCst) == 1);
134 @atomicStore(u32, &x, 12345678, .SeqCst);
135 try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678);
136}
137
138test "atomic store comptime" {
139 comptime try testAtomicStore();
140 try testAtomicStore();
141}
142
143fn testAtomicStore() !void {
144 var x: u32 = 0;
145 @atomicStore(u32, &x, 1, .SeqCst);
146 try expect(@atomicLoad(u32, &x, .SeqCst) == 1);
147 @atomicStore(u32, &x, 12345678, .SeqCst);
148 try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678);
149}
150
151test "atomicrmw with floats" {
152 switch (builtin.target.cpu.arch) {
153 // https://github.com/ziglang/zig/issues/4457
154 .aarch64, .arm, .thumb, .riscv64 => return error.SkipZigTest,
155 else => {},
156 }
157 try testAtomicRmwFloat();
158 comptime try testAtomicRmwFloat();
159}
160
161fn testAtomicRmwFloat() !void {
162 var x: f32 = 0;
163 try expect(x == 0);
164 _ = @atomicRmw(f32, &x, .Xchg, 1, .SeqCst);
165 try expect(x == 1);
166 _ = @atomicRmw(f32, &x, .Add, 5, .SeqCst);
167 try expect(x == 6);
168 _ = @atomicRmw(f32, &x, .Sub, 2, .SeqCst);
169 try expect(x == 4);
170}
171
172test "atomicrmw with ints" {
173 try testAtomicRmwInt();
174 comptime try testAtomicRmwInt();
175}
176
177fn testAtomicRmwInt() !void {
178 var x: u8 = 1;
179 var res = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst);
180 try expect(x == 3 and res == 1);
181 _ = @atomicRmw(u8, &x, .Add, 3, .SeqCst);
182 try expect(x == 6);
183 _ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst);
184 try expect(x == 5);
185 _ = @atomicRmw(u8, &x, .And, 4, .SeqCst);
186 try expect(x == 4);
187 _ = @atomicRmw(u8, &x, .Nand, 4, .SeqCst);
188 try expect(x == 0xfb);
189 _ = @atomicRmw(u8, &x, .Or, 6, .SeqCst);
190 try expect(x == 0xff);
191 _ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst);
192 try expect(x == 0xfd);
193
194 _ = @atomicRmw(u8, &x, .Max, 1, .SeqCst);
195 try expect(x == 0xfd);
196 _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
197 try expect(x == 1);
198}
199
200test "atomics with different types" {
201 try testAtomicsWithType(bool, true, false);
202 inline for (.{ u1, i4, u5, i15, u24 }) |T| {
203 var x: T = 0;
204 try testAtomicsWithType(T, 0, 1);
205 }
206 try testAtomicsWithType(u0, 0, 0);
207 try testAtomicsWithType(i0, 0, 0);
208}
209
210fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {
211 var x: T = b;
212 @atomicStore(T, &x, a, .SeqCst);
213 try expect(x == a);
214 try expect(@atomicLoad(T, &x, .SeqCst) == a);
215 try expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a);
216 try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null);
217 if (@sizeOf(T) != 0)
218 try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a);
219}
test/behavior/await_struct.zig created+44
...@@ -0,0 +1,44 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5const Foo = struct {
6 x: i32,
7};
8
9var await_a_promise: anyframe = undefined;
10var await_final_result = Foo{ .x = 0 };
11
12test "coroutine await struct" {
13 await_seq('a');
14 var p = async await_amain();
15 await_seq('f');
16 resume await_a_promise;
17 await_seq('i');
18 try expect(await_final_result.x == 1234);
19 try expect(std.mem.eql(u8, &await_points, "abcdefghi"));
20}
21fn await_amain() callconv(.Async) void {
22 await_seq('b');
23 var p = async await_another();
24 await_seq('e');
25 await_final_result = await p;
26 await_seq('h');
27}
28fn await_another() callconv(.Async) Foo {
29 await_seq('c');
30 suspend {
31 await_seq('d');
32 await_a_promise = @frame();
33 }
34 await_seq('g');
35 return Foo{ .x = 1234 };
36}
37
38var await_points = [_]u8{0} ** "abcdefghi".len;
39var await_seq_index: usize = 0;
40
41fn await_seq(c: u8) void {
42 await_points[await_seq_index] = c;
43 await_seq_index += 1;
44}
test/behavior/bit_shifting.zig created+104
...@@ -0,0 +1,104 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
5 const key_bits = @typeInfo(Key).Int.bits;
6 std.debug.assert(Key == std.meta.Int(.unsigned, key_bits));
7 std.debug.assert(key_bits >= mask_bit_count);
8 const shard_key_bits = mask_bit_count;
9 const ShardKey = std.meta.Int(.unsigned, mask_bit_count);
10 const shift_amount = key_bits - shard_key_bits;
11 return struct {
12 const Self = @This();
13 shards: [1 << shard_key_bits]?*Node,
14
15 pub fn create() Self {
16 return Self{ .shards = [_]?*Node{null} ** (1 << shard_key_bits) };
17 }
18
19 fn getShardKey(key: Key) ShardKey {
20 // https://github.com/ziglang/zig/issues/1544
21 // this special case is needed because you can't u32 >> 32.
22 if (ShardKey == u0) return 0;
23
24 // this can be u1 >> u0
25 const shard_key = key >> shift_amount;
26
27 // TODO: https://github.com/ziglang/zig/issues/1544
28 // This cast could be implicit if we teach the compiler that
29 // u32 >> 30 -> u2
30 return @intCast(ShardKey, shard_key);
31 }
32
33 pub fn put(self: *Self, node: *Node) void {
34 const shard_key = Self.getShardKey(node.key);
35 node.next = self.shards[shard_key];
36 self.shards[shard_key] = node;
37 }
38
39 pub fn get(self: *Self, key: Key) ?*Node {
40 const shard_key = Self.getShardKey(key);
41 var maybe_node = self.shards[shard_key];
42 while (maybe_node) |node| : (maybe_node = node.next) {
43 if (node.key == key) return node;
44 }
45 return null;
46 }
47
48 pub const Node = struct {
49 key: Key,
50 value: V,
51 next: ?*Node,
52
53 pub fn init(self: *Node, key: Key, value: V) void {
54 self.key = key;
55 self.value = value;
56 self.next = null;
57 }
58 };
59 };
60}
61
62test "sharded table" {
63 // realistic 16-way sharding
64 try testShardedTable(u32, 4, 8);
65
66 try testShardedTable(u5, 0, 32); // ShardKey == u0
67 try testShardedTable(u5, 2, 32);
68 try testShardedTable(u5, 5, 32);
69
70 try testShardedTable(u1, 0, 2);
71 try testShardedTable(u1, 1, 2); // this does u1 >> u0
72
73 try testShardedTable(u0, 0, 1);
74}
75fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) !void {
76 const Table = ShardedTable(Key, mask_bit_count, void);
77
78 var table = Table.create();
79 var node_buffer: [node_count]Table.Node = undefined;
80 for (node_buffer) |*node, i| {
81 const key = @intCast(Key, i);
82 try expect(table.get(key) == null);
83 node.init(key, {});
84 table.put(node);
85 }
86
87 for (node_buffer) |*node, i| {
88 try expect(table.get(@intCast(Key, i)) == node);
89 }
90}
91
92// #2225
93test "comptime shr of BigInt" {
94 comptime {
95 var n0 = 0xdeadbeef0000000000000000;
96 try expect(n0 >> 64 == 0xdeadbeef);
97 var n1 = 17908056155735594659;
98 try expect(n1 >> 64 == 0);
99 }
100}
101
102test "comptime shift safety check" {
103 const x = @as(usize, 42) << @sizeOf(usize);
104}
test/behavior/bitcast.zig created+197
...@@ -0,0 +1,197 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;
5const maxInt = std.math.maxInt;
6const native_endian = builtin.target.cpu.arch.endian();
7
8test "@bitCast i32 -> u32" {
9 try testBitCast_i32_u32();
10 comptime try testBitCast_i32_u32();
11}
12
13fn testBitCast_i32_u32() !void {
14 try expect(conv(-1) == maxInt(u32));
15 try expect(conv2(maxInt(u32)) == -1);
16}
17
18fn conv(x: i32) u32 {
19 return @bitCast(u32, x);
20}
21fn conv2(x: u32) i32 {
22 return @bitCast(i32, x);
23}
24
25test "@bitCast extern enum to its integer type" {
26 const SOCK = extern enum {
27 A,
28 B,
29
30 fn testBitCastExternEnum() !void {
31 var SOCK_DGRAM = @This().B;
32 var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
33 try expect(sock_dgram == 1);
34 }
35 };
36
37 try SOCK.testBitCastExternEnum();
38 comptime try SOCK.testBitCastExternEnum();
39}
40
41test "@bitCast packed structs at runtime and comptime" {
42 const Full = packed struct {
43 number: u16,
44 };
45 const Divided = packed struct {
46 half1: u8,
47 quarter3: u4,
48 quarter4: u4,
49 };
50 const S = struct {
51 fn doTheTest() !void {
52 var full = Full{ .number = 0x1234 };
53 var two_halves = @bitCast(Divided, full);
54 switch (native_endian) {
55 .Big => {
56 try expect(two_halves.half1 == 0x12);
57 try expect(two_halves.quarter3 == 0x3);
58 try expect(two_halves.quarter4 == 0x4);
59 },
60 .Little => {
61 try expect(two_halves.half1 == 0x34);
62 try expect(two_halves.quarter3 == 0x2);
63 try expect(two_halves.quarter4 == 0x1);
64 },
65 }
66 }
67 };
68 try S.doTheTest();
69 comptime try S.doTheTest();
70}
71
72test "@bitCast extern structs at runtime and comptime" {
73 const Full = extern struct {
74 number: u16,
75 };
76 const TwoHalves = extern struct {
77 half1: u8,
78 half2: u8,
79 };
80 const S = struct {
81 fn doTheTest() !void {
82 var full = Full{ .number = 0x1234 };
83 var two_halves = @bitCast(TwoHalves, full);
84 switch (native_endian) {
85 .Big => {
86 try expect(two_halves.half1 == 0x12);
87 try expect(two_halves.half2 == 0x34);
88 },
89 .Little => {
90 try expect(two_halves.half1 == 0x34);
91 try expect(two_halves.half2 == 0x12);
92 },
93 }
94 }
95 };
96 try S.doTheTest();
97 comptime try S.doTheTest();
98}
99
100test "bitcast packed struct to integer and back" {
101 const LevelUpMove = packed struct {
102 move_id: u9,
103 level: u7,
104 };
105 const S = struct {
106 fn doTheTest() !void {
107 var move = LevelUpMove{ .move_id = 1, .level = 2 };
108 var v = @bitCast(u16, move);
109 var back_to_a_move = @bitCast(LevelUpMove, v);
110 try expect(back_to_a_move.move_id == 1);
111 try expect(back_to_a_move.level == 2);
112 }
113 };
114 try S.doTheTest();
115 comptime try S.doTheTest();
116}
117
118test "implicit cast to error union by returning" {
119 const S = struct {
120 fn entry() !void {
121 try expect((func(-1) catch unreachable) == maxInt(u64));
122 }
123 pub fn func(sz: i64) anyerror!u64 {
124 return @bitCast(u64, sz);
125 }
126 };
127 try S.entry();
128 comptime try S.entry();
129}
130
131// issue #3010: compiler segfault
132test "bitcast literal [4]u8 param to u32" {
133 const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
134 try expect(ip == maxInt(u32));
135}
136
137test "bitcast packed struct literal to byte" {
138 const Foo = packed struct {
139 value: u8,
140 };
141 const casted = @bitCast(u8, Foo{ .value = 0xF });
142 try expect(casted == 0xf);
143}
144
145test "comptime bitcast used in expression has the correct type" {
146 const Foo = packed struct {
147 value: u8,
148 };
149 try expect(@bitCast(u8, Foo{ .value = 0xF }) == 0xf);
150}
151
152test "bitcast result to _" {
153 _ = @bitCast(u8, @as(i8, 1));
154}
155
156test "nested bitcast" {
157 const S = struct {
158 fn moo(x: isize) !void {
159 try @import("std").testing.expectEqual(@intCast(isize, 42), x);
160 }
161
162 fn foo(x: isize) !void {
163 try @This().moo(
164 @bitCast(isize, if (x != 0) @bitCast(usize, x) else @bitCast(usize, x)),
165 );
166 }
167 };
168
169 try S.foo(42);
170 comptime try S.foo(42);
171}
172
173test "bitcast passed as tuple element" {
174 const S = struct {
175 fn foo(args: anytype) !void {
176 comptime try expect(@TypeOf(args[0]) == f32);
177 try expect(args[0] == 12.34);
178 }
179 };
180 try S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))});
181}
182
183test "triple level result location with bitcast sandwich passed as tuple element" {
184 const S = struct {
185 fn foo(args: anytype) !void {
186 comptime try expect(@TypeOf(args[0]) == f64);
187 try expect(args[0] > 12.33 and args[0] < 12.35);
188 }
189 };
190 try S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
191}
192
193test "bitcast generates a temporary value" {
194 var y = @as(u16, 0x55AA);
195 const x = @bitCast(u16, @bitCast([2]u8, y));
196 try expectEqual(y, x);
197}
test/behavior/bitreverse.zig created+69
...@@ -0,0 +1,69 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const minInt = std.math.minInt;
4
5test "@bitReverse" {
6 comptime try testBitReverse();
7 try testBitReverse();
8}
9
10fn testBitReverse() !void {
11 // using comptime_ints, unsigned
12 try expect(@bitReverse(u0, 0) == 0);
13 try expect(@bitReverse(u5, 0x12) == 0x9);
14 try expect(@bitReverse(u8, 0x12) == 0x48);
15 try expect(@bitReverse(u16, 0x1234) == 0x2c48);
16 try expect(@bitReverse(u24, 0x123456) == 0x6a2c48);
17 try expect(@bitReverse(u32, 0x12345678) == 0x1e6a2c48);
18 try expect(@bitReverse(u40, 0x123456789a) == 0x591e6a2c48);
19 try expect(@bitReverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
20 try expect(@bitReverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
21 try expect(@bitReverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
22 try expect(@bitReverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
23
24 // using runtime uints, unsigned
25 var num0: u0 = 0;
26 try expect(@bitReverse(u0, num0) == 0);
27 var num5: u5 = 0x12;
28 try expect(@bitReverse(u5, num5) == 0x9);
29 var num8: u8 = 0x12;
30 try expect(@bitReverse(u8, num8) == 0x48);
31 var num16: u16 = 0x1234;
32 try expect(@bitReverse(u16, num16) == 0x2c48);
33 var num24: u24 = 0x123456;
34 try expect(@bitReverse(u24, num24) == 0x6a2c48);
35 var num32: u32 = 0x12345678;
36 try expect(@bitReverse(u32, num32) == 0x1e6a2c48);
37 var num40: u40 = 0x123456789a;
38 try expect(@bitReverse(u40, num40) == 0x591e6a2c48);
39 var num48: u48 = 0x123456789abc;
40 try expect(@bitReverse(u48, num48) == 0x3d591e6a2c48);
41 var num56: u56 = 0x123456789abcde;
42 try expect(@bitReverse(u56, num56) == 0x7b3d591e6a2c48);
43 var num64: u64 = 0x123456789abcdef1;
44 try expect(@bitReverse(u64, num64) == 0x8f7b3d591e6a2c48);
45 var num128: u128 = 0x123456789abcdef11121314151617181;
46 try expect(@bitReverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
47
48 // using comptime_ints, signed, positive
49 try expect(@bitReverse(u8, @as(u8, 0)) == 0);
50 try expect(@bitReverse(i8, @bitCast(i8, @as(u8, 0x92))) == @bitCast(i8, @as(u8, 0x49)));
51 try expect(@bitReverse(i16, @bitCast(i16, @as(u16, 0x1234))) == @bitCast(i16, @as(u16, 0x2c48)));
52 try expect(@bitReverse(i24, @bitCast(i24, @as(u24, 0x123456))) == @bitCast(i24, @as(u24, 0x6a2c48)));
53 try expect(@bitReverse(i32, @bitCast(i32, @as(u32, 0x12345678))) == @bitCast(i32, @as(u32, 0x1e6a2c48)));
54 try expect(@bitReverse(i40, @bitCast(i40, @as(u40, 0x123456789a))) == @bitCast(i40, @as(u40, 0x591e6a2c48)));
55 try expect(@bitReverse(i48, @bitCast(i48, @as(u48, 0x123456789abc))) == @bitCast(i48, @as(u48, 0x3d591e6a2c48)));
56 try expect(@bitReverse(i56, @bitCast(i56, @as(u56, 0x123456789abcde))) == @bitCast(i56, @as(u56, 0x7b3d591e6a2c48)));
57 try expect(@bitReverse(i64, @bitCast(i64, @as(u64, 0x123456789abcdef1))) == @bitCast(i64, @as(u64, 0x8f7b3d591e6a2c48)));
58 try expect(@bitReverse(i128, @bitCast(i128, @as(u128, 0x123456789abcdef11121314151617181))) == @bitCast(i128, @as(u128, 0x818e868a828c84888f7b3d591e6a2c48)));
59
60 // using signed, negative. Compare to runtime ints returned from llvm.
61 var neg8: i8 = -18;
62 try expect(@bitReverse(i8, @as(i8, -18)) == @bitReverse(i8, neg8));
63 var neg16: i16 = -32694;
64 try expect(@bitReverse(i16, @as(i16, -32694)) == @bitReverse(i16, neg16));
65 var neg24: i24 = -6773785;
66 try expect(@bitReverse(i24, @as(i24, -6773785)) == @bitReverse(i24, neg24));
67 var neg32: i32 = -16773785;
68 try expect(@bitReverse(i32, @as(i32, -16773785)) == @bitReverse(i32, neg32));
69}
test/behavior/bool.zig created+35
...@@ -0,0 +1,35 @@
1const expect = @import("std").testing.expect;
2
3test "bool literals" {
4 try expect(true);
5 try expect(!false);
6}
7
8test "cast bool to int" {
9 const t = true;
10 const f = false;
11 try expect(@boolToInt(t) == @as(u32, 1));
12 try expect(@boolToInt(f) == @as(u32, 0));
13 try nonConstCastBoolToInt(t, f);
14}
15
16fn nonConstCastBoolToInt(t: bool, f: bool) !void {
17 try expect(@boolToInt(t) == @as(u32, 1));
18 try expect(@boolToInt(f) == @as(u32, 0));
19}
20
21test "bool cmp" {
22 try expect(testBoolCmp(true, false) == false);
23}
24fn testBoolCmp(a: bool, b: bool) bool {
25 return a == b;
26}
27
28const global_f = false;
29const global_t = true;
30const not_global_f = !global_f;
31const not_global_t = !global_t;
32test "compile time bool not" {
33 try expect(not_global_f);
34 try expect(!not_global_t);
35}
test/behavior/bugs/1025.zig created+12
...@@ -0,0 +1,12 @@
1const A = struct {
2 B: type,
3};
4
5fn getA() A {
6 return A{ .B = u8 };
7}
8
9test "bug 1025" {
10 const a = getA();
11 try @import("std").testing.expect(a.B == u8);
12}
test/behavior/bugs/1076.zig created+23
...@@ -0,0 +1,23 @@
1const std = @import("std");
2const mem = std.mem;
3const expect = std.testing.expect;
4
5test "comptime code should not modify constant data" {
6 try testCastPtrOfArrayToSliceAndPtr();
7 comptime try testCastPtrOfArrayToSliceAndPtr();
8}
9
10fn testCastPtrOfArrayToSliceAndPtr() !void {
11 {
12 var array = "aoeu".*;
13 const x: [*]u8 = &array;
14 x[0] += 1;
15 try expect(mem.eql(u8, array[0..], "boeu"));
16 }
17 {
18 var array: [4]u8 = "aoeu".*;
19 const x: [*]u8 = &array;
20 x[0] += 1;
21 try expect(mem.eql(u8, array[0..], "boeu"));
22 }
23}
test/behavior/bugs/1111.zig created+11
...@@ -0,0 +1,11 @@
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 }
11}
test/behavior/bugs/1120.zig created+23
...@@ -0,0 +1,23 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const A = packed struct {
5 a: u2,
6 b: u6,
7};
8const B = packed struct {
9 q: u8,
10 a: u2,
11 b: u6,
12};
13test "bug 1120" {
14 var a = A{ .a = 2, .b = 2 };
15 var b = B{ .q = 22, .a = 3, .b = 2 };
16 var t: usize = 0;
17 const ptr = switch (t) {
18 0 => &a.a,
19 1 => &b.a,
20 else => unreachable,
21 };
22 try expect(ptr.* == 2);
23}
test/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 try std.testing.expect(s.f.?() == 1234);
15}
test/behavior/bugs/1310.zig created+24
...@@ -0,0 +1,24 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4pub const VM = ?[*]const struct_InvocationTable_;
5pub const struct_InvocationTable_ = extern struct {
6 GetVM: ?fn (?[*]VM) callconv(.C) c_int,
7};
8
9pub const struct_VM_ = extern struct {
10 functions: ?[*]const struct_InvocationTable_,
11};
12
13//excised output from stdlib.h etc
14
15pub const InvocationTable_ = struct_InvocationTable_;
16pub const VM_ = struct_VM_;
17
18fn agent_callback(_vm: [*]VM, options: [*]u8) callconv(.C) i32 {
19 return 11;
20}
21
22test "fixed" {
23 try expect(agent_callback(undefined, undefined) == 11);
24}
test/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 try std.testing.expect(@as(std.meta.Tag(B), a.b) == std.meta.Tag(B).c);
17 a = A{ .b = B.None };
18 try std.testing.expect(@as(std.meta.Tag(B), a.b) == std.meta.Tag(B).None);
19}
test/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 try std.testing.expect(a.D == 1);
21}
test/behavior/bugs/1421.zig created+13
...@@ -0,0 +1,13 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const S = struct {
5 fn method() std.builtin.TypeInfo {
6 return @typeInfo(S);
7 }
8};
9
10test "functions with return type required to be comptime are generic" {
11 const ti = S.method();
12 try expect(@as(std.builtin.TypeId, ti) == std.builtin.TypeId.Struct);
13}
test/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 try std.testing.expect((union_or_err catch unreachable).Color == 1234);
11}
test/behavior/bugs/1467.zig created+7
...@@ -0,0 +1,7 @@
1pub const E = enum(u32) { A, B, C };
2pub const S = extern struct {
3 e: E,
4};
5test "bug 1467" {
6 const s: S = undefined;
7}
test/behavior/bugs/1486.zig created+10
...@@ -0,0 +1,10 @@
1const expect = @import("std").testing.expect;
2
3const ptr = &global;
4var global: u64 = 123;
5
6test "constant pointer to global variable causes runtime load" {
7 global = 1234;
8 try expect(&global == ptr);
9 try expect(ptr.* == 1234);
10}
test/behavior/bugs/1500.zig created+10
...@@ -0,0 +1,10 @@
1const A = struct {
2 b: B,
3};
4
5const B = fn (A) void;
6
7test "allow these dependencies" {
8 var a: A = undefined;
9 var b: B = undefined;
10}
test/behavior/bugs/1607.zig created+15
...@@ -0,0 +1,15 @@
1const std = @import("std");
2const testing = std.testing;
3
4const a = [_]u8{ 1, 2, 3 };
5
6fn checkAddress(s: []const u8) !void {
7 for (s) |*i, j| {
8 try testing.expect(i == &a[j]);
9 }
10}
11
12test "slices pointing at the same address as global array." {
13 try checkAddress(&a);
14 comptime try checkAddress(&a);
15}
test/behavior/bugs/1735.zig created+46
...@@ -0,0 +1,46 @@
1const std = @import("std");
2
3const mystruct = struct {
4 pending: ?listofstructs,
5};
6pub fn TailQueue(comptime T: type) type {
7 return struct {
8 const Self = @This();
9
10 pub const Node = struct {
11 prev: ?*Node,
12 next: ?*Node,
13 data: T,
14 };
15
16 first: ?*Node,
17 last: ?*Node,
18 len: usize,
19
20 pub fn init() Self {
21 return Self{
22 .first = null,
23 .last = null,
24 .len = 0,
25 };
26 }
27 };
28}
29const listofstructs = TailQueue(mystruct);
30
31const a = struct {
32 const Self = @This();
33
34 foo: listofstructs,
35
36 pub fn init() Self {
37 return Self{
38 .foo = listofstructs.init(),
39 };
40 }
41};
42
43test "intialization" {
44 var t = a.init();
45 try std.testing.expect(t.foo.len == 0);
46}
test/behavior/bugs/1741.zig created+6
...@@ -0,0 +1,6 @@
1const std = @import("std");
2
3test "fixed" {
4 const x: f32 align(128) = 12.34;
5 try std.testing.expect(@ptrToInt(&x) % 128 == 0);
6}
test/behavior/bugs/1851.zig created+26
...@@ -0,0 +1,26 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "allocation and looping over 3-byte integer" {
5 try expect(@sizeOf(u24) == 4);
6 try expect(@sizeOf([1]u24) == 4);
7 try expect(@alignOf(u24) == 4);
8 try expect(@alignOf([1]u24) == 4);
9
10 var x = try std.testing.allocator.alloc(u24, 2);
11 defer std.testing.allocator.free(x);
12 try expect(x.len == 2);
13 x[0] = 0xFFFFFF;
14 x[1] = 0xFFFFFF;
15
16 const bytes = std.mem.sliceAsBytes(x);
17 try expect(@TypeOf(bytes) == []align(4) u8);
18 try expect(bytes.len == 8);
19
20 for (bytes) |*b| {
21 b.* = 0x00;
22 }
23
24 try expect(x[0] == 0x00);
25 try expect(x[1] == 0x00);
26}
test/behavior/bugs/1914.zig created+31
...@@ -0,0 +1,31 @@
1const std = @import("std");
2
3const A = struct {
4 b_list_pointer: *const []B,
5};
6const B = struct {
7 a_pointer: *const A,
8};
9
10const b_list: []B = &[_]B{};
11const a = A{ .b_list_pointer = &b_list };
12
13test "segfault bug" {
14 const assert = std.debug.assert;
15 const obj = B{ .a_pointer = &a };
16 assert(obj.a_pointer == &a); // this makes zig crash
17}
18
19const A2 = struct {
20 pointer: *B,
21};
22
23pub const B2 = struct {
24 pointer_array: []*A2,
25};
26
27var b_value = B2{ .pointer_array = &[_]*A2{} };
28
29test "basic stuff" {
30 std.debug.assert(&b_value == &b_value);
31}
test/behavior/bugs/2006.zig created+12
...@@ -0,0 +1,12 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const S = struct {
5 p: *S,
6};
7test "bug 2006" {
8 var a: S = undefined;
9 a = S{ .p = undefined };
10 try expect(@sizeOf(S) != 0);
11 try expect(@sizeOf(*void) == 0);
12}
test/behavior/bugs/2114.zig created+19
...@@ -0,0 +1,19 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const math = std.math;
4
5fn ctz(x: anytype) usize {
6 return @ctz(@TypeOf(x), x);
7}
8
9test "fixed" {
10 try testClz();
11 comptime try testClz();
12}
13
14fn testClz() !void {
15 try expect(ctz(@as(u128, 0x40000000000000000000000000000000)) == 126);
16 try expect(math.rotl(u128, @as(u128, 0x40000000000000000000000000000000), @as(u8, 1)) == @as(u128, 0x80000000000000000000000000000000));
17 try expect(ctz(@as(u128, 0x80000000000000000000000000000000)) == 127);
18 try expect(ctz(math.rotl(u128, @as(u128, 0x40000000000000000000000000000000), @as(u8, 1))) == 127);
19}
test/behavior/bugs/2346.zig created+6
...@@ -0,0 +1,6 @@
1test "fixed" {
2 const a: *void = undefined;
3 const b: *[1]void = a;
4 const c: *[0]u8 = undefined;
5 const d: []u8 = c;
6}
test/behavior/bugs/2578.zig created+12
...@@ -0,0 +1,12 @@
1const Foo = struct {
2 y: u8,
3};
4
5var foo: Foo = undefined;
6const t = &foo;
7
8fn bar(pointer: ?*c_void) void {}
9
10test "fixed" {
11 bar(t);
12}
test/behavior/bugs/2692.zig created+6
...@@ -0,0 +1,6 @@
1fn foo(a: []u8) void {}
2
3test "address of 0 length array" {
4 var pt: [0]u8 = undefined;
5 foo(&pt);
6}
test/behavior/bugs/2889.zig created+31
...@@ -0,0 +1,31 @@
1const std = @import("std");
2
3const source = "A-";
4
5fn parseNote() ?i32 {
6 const letter = source[0];
7 const modifier = source[1];
8
9 const semitone = blk: {
10 if (letter == 'C' and modifier == '-') break :blk @as(i32, 0);
11 if (letter == 'C' and modifier == '#') break :blk @as(i32, 1);
12 if (letter == 'D' and modifier == '-') break :blk @as(i32, 2);
13 if (letter == 'D' and modifier == '#') break :blk @as(i32, 3);
14 if (letter == 'E' and modifier == '-') break :blk @as(i32, 4);
15 if (letter == 'F' and modifier == '-') break :blk @as(i32, 5);
16 if (letter == 'F' and modifier == '#') break :blk @as(i32, 6);
17 if (letter == 'G' and modifier == '-') break :blk @as(i32, 7);
18 if (letter == 'G' and modifier == '#') break :blk @as(i32, 8);
19 if (letter == 'A' and modifier == '-') break :blk @as(i32, 9);
20 if (letter == 'A' and modifier == '#') break :blk @as(i32, 10);
21 if (letter == 'B' and modifier == '-') break :blk @as(i32, 11);
22 return null;
23 };
24
25 return semitone;
26}
27
28test "fixed" {
29 const result = parseNote();
30 try std.testing.expect(result.? == 9);
31}
test/behavior/bugs/3007.zig created+23
...@@ -0,0 +1,23 @@
1const std = @import("std");
2
3const Foo = struct {
4 free: bool,
5
6 pub const FooError = error{NotFree};
7};
8
9var foo = Foo{ .free = true };
10var default_foo: ?*Foo = null;
11
12fn get_foo() Foo.FooError!*Foo {
13 if (foo.free) {
14 foo.free = false;
15 return &foo;
16 }
17 return error.NotFree;
18}
19
20test "fixed" {
21 default_foo = get_foo() catch null; // This Line
22 try std.testing.expect(!default_foo.?.free);
23}
test/behavior/bugs/3046.zig created+19
...@@ -0,0 +1,19 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const SomeStruct = struct {
5 field: i32,
6};
7
8fn couldFail() anyerror!i32 {
9 return 1;
10}
11
12var some_struct: SomeStruct = undefined;
13
14test "fixed" {
15 some_struct = SomeStruct{
16 .field = couldFail() catch |_| @as(i32, 0),
17 };
18 try expect(some_struct.field == 1);
19}
test/behavior/bugs/3112.zig created+17
...@@ -0,0 +1,17 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const State = struct {
5 const Self = @This();
6 enter: fn (previous: ?Self) void,
7};
8
9fn prev(p: ?State) void {
10 expect(p == null) catch @panic("test failure");
11}
12
13test "zig test crash" {
14 var global: State = undefined;
15 global.enter = prev;
16 global.enter(null);
17}
test/behavior/bugs/3367.zig created+12
...@@ -0,0 +1,12 @@
1const Foo = struct {
2 usingnamespace Mixin;
3};
4
5const Mixin = struct {
6 pub fn two(self: Foo) void {}
7};
8
9test "container member access usingnamespace decls" {
10 var foo = Foo{};
11 foo.two();
12}
test/behavior/bugs/3384.zig created+11
...@@ -0,0 +1,11 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "resolve array slice using builtin" {
5 try expect(@hasDecl(@This(), "std") == true);
6 try expect(@hasDecl(@This(), "std"[0..0]) == false);
7 try expect(@hasDecl(@This(), "std"[0..1]) == false);
8 try expect(@hasDecl(@This(), "std"[0..2]) == false);
9 try expect(@hasDecl(@This(), "std"[0..3]) == true);
10 try expect(@hasDecl(@This(), "std"[0..]) == true);
11}
test/behavior/bugs/3468.zig created+6
...@@ -0,0 +1,6 @@
1// zig fmt: off
2test "pointer deref next to assignment" {
3 var a:i32=2;
4 var b=&a;
5 b.*=3;
6}
test/behavior/bugs/3586.zig created+11
...@@ -0,0 +1,11 @@
1const NoteParams = struct {};
2
3const Container = struct {
4 params: ?NoteParams,
5};
6
7test "fixed" {
8 var ctr = Container{
9 .params = NoteParams{},
10 };
11}
test/behavior/bugs/3742.zig created+38
...@@ -0,0 +1,38 @@
1const std = @import("std");
2
3pub const GET = struct {
4 key: []const u8,
5
6 pub fn init(key: []const u8) GET {
7 return .{ .key = key };
8 }
9
10 pub const Redis = struct {
11 pub const Command = struct {
12 pub fn serialize(self: GET, comptime rootSerializer: type) void {
13 return rootSerializer.serializeCommand(.{ "GET", self.key });
14 }
15 };
16 };
17};
18
19pub fn isCommand(comptime T: type) bool {
20 const tid = @typeInfo(T);
21 return (tid == .Struct or tid == .Enum or tid == .Union) and
22 @hasDecl(T, "Redis") and @hasDecl(T.Redis, "Command");
23}
24
25pub const ArgSerializer = struct {
26 pub fn serializeCommand(command: anytype) void {
27 const CmdT = @TypeOf(command);
28
29 if (comptime isCommand(CmdT)) {
30 // COMMENTING THE NEXT LINE REMOVES THE ERROR
31 return CmdT.Redis.Command.serialize(command, ArgSerializer);
32 }
33 }
34};
35
36test "fixed" {
37 ArgSerializer.serializeCommand(GET.init("banana"));
38}
test/behavior/bugs/394.zig created+18
...@@ -0,0 +1,18 @@
1const E = union(enum) {
2 A: [9]u8,
3 B: u64,
4};
5const S = struct {
6 x: u8,
7 y: E,
8};
9
10const expect = @import("std").testing.expect;
11
12test "bug 394 fixed" {
13 const x = S{
14 .x = 3,
15 .y = E{ .B = 1 },
16 };
17 try expect(x.x == 3);
18}
test/behavior/bugs/421.zig created+15
...@@ -0,0 +1,15 @@
1const expect = @import("std").testing.expect;
2
3test "bitCast to array" {
4 comptime try testBitCastArray();
5 try testBitCastArray();
6}
7
8fn testBitCastArray() !void {
9 try expect(extractOne64(0x0123456789abcdef0123456789abcdef) == 0x0123456789abcdef);
10}
11
12fn extractOne64(a: u128) u64 {
13 const x = @bitCast([2]u64, a);
14 return x[1];
15}
test/behavior/bugs/4328.zig created+71
...@@ -0,0 +1,71 @@
1const expectEqual = @import("std").testing.expectEqual;
2
3const FILE = extern struct {
4 dummy_field: u8,
5};
6
7extern fn printf([*c]const u8, ...) c_int;
8extern fn fputs([*c]const u8, noalias [*c]FILE) c_int;
9extern fn ftell([*c]FILE) c_long;
10extern fn fopen([*c]const u8, [*c]const u8) [*c]FILE;
11
12const S = extern struct {
13 state: c_short,
14
15 extern fn s_do_thing([*c]S, b: c_int) c_short;
16};
17
18test "Extern function calls in @TypeOf" {
19 const Test = struct {
20 fn test_fn_1(a: anytype, b: anytype) @TypeOf(printf("%d %s\n", a, b)) {
21 return 0;
22 }
23
24 fn test_fn_2(a: anytype) @TypeOf((S{ .state = 0 }).s_do_thing(a)) {
25 return 1;
26 }
27
28 fn doTheTest() !void {
29 try expectEqual(c_int, @TypeOf(test_fn_1(0, 42)));
30 try expectEqual(c_short, @TypeOf(test_fn_2(0)));
31 }
32 };
33
34 try Test.doTheTest();
35 comptime try Test.doTheTest();
36}
37
38test "Peer resolution of extern function calls in @TypeOf" {
39 const Test = struct {
40 fn test_fn() @TypeOf(ftell(null), fputs(null, null)) {
41 return 0;
42 }
43
44 fn doTheTest() !void {
45 try expectEqual(c_long, @TypeOf(test_fn()));
46 }
47 };
48
49 try Test.doTheTest();
50 comptime try Test.doTheTest();
51}
52
53test "Extern function calls, dereferences and field access in @TypeOf" {
54 const Test = struct {
55 fn test_fn_1(a: c_long) @TypeOf(fopen("test", "r").*) {
56 return .{ .dummy_field = 0 };
57 }
58
59 fn test_fn_2(a: anytype) @TypeOf(fopen("test", "r").*.dummy_field) {
60 return 255;
61 }
62
63 fn doTheTest() !void {
64 try expectEqual(FILE, @TypeOf(test_fn_1(0)));
65 try expectEqual(u8, @TypeOf(test_fn_2(0)));
66 }
67 };
68
69 try Test.doTheTest();
70 comptime try Test.doTheTest();
71}
test/behavior/bugs/4560.zig created+32
...@@ -0,0 +1,32 @@
1const std = @import("std");
2
3test "fixed" {
4 var s: S = .{
5 .a = 1,
6 .b = .{
7 .size = 123,
8 .max_distance_from_start_index = 456,
9 },
10 };
11 try std.testing.expect(s.a == 1);
12 try std.testing.expect(s.b.size == 123);
13 try std.testing.expect(s.b.max_distance_from_start_index == 456);
14}
15
16const S = struct {
17 a: u32,
18 b: Map,
19
20 const Map = StringHashMap(*S);
21};
22
23pub fn StringHashMap(comptime V: type) type {
24 return HashMap([]const u8, V);
25}
26
27pub fn HashMap(comptime K: type, comptime V: type) type {
28 return struct {
29 size: usize,
30 max_distance_from_start_index: usize,
31 };
32}
test/behavior/bugs/4769_a.zig created+1
...@@ -0,0 +1 @@
1//
test/behavior/bugs/4769_b.zig created+1
...@@ -0,0 +1 @@
1//!
test/behavior/bugs/4769_c.zig created+1
...@@ -0,0 +1 @@
1///
\ No newline at end of file
test/behavior/bugs/4954.zig created+8
...@@ -0,0 +1,8 @@
1fn f(buf: []u8) void {
2 var ptr = &buf[@sizeOf(u32)];
3}
4
5test "crash" {
6 var buf: [4096]u8 = undefined;
7 f(&buf);
8}
test/behavior/bugs/529.zig created+14
...@@ -0,0 +1,14 @@
1const A = extern struct {
2 field: c_int,
3};
4
5extern fn issue529(?*A) void;
6
7comptime {
8 _ = @import("529_other_file_2.zig");
9}
10
11test "issue 529 fixed" {
12 @import("529_other_file.zig").issue529(null);
13 issue529(null);
14}
test/behavior/bugs/529_other_file.zig created+5
...@@ -0,0 +1,5 @@
1pub const A = extern struct {
2 field: c_int,
3};
4
5pub extern fn issue529(?*A) void;
test/behavior/bugs/529_other_file_2.zig created+4
...@@ -0,0 +1,4 @@
1pub const A = extern struct {
2 field: c_int,
3};
4export fn issue529(a: ?*A) void {}
test/behavior/bugs/5398.zig created+31
...@@ -0,0 +1,31 @@
1const std = @import("std");
2const testing = std.testing;
3
4pub const Mesh = struct {
5 id: u32,
6};
7pub const Material = struct {
8 transparent: bool = true,
9 emits_shadows: bool = true,
10 render_color: bool = true,
11};
12pub const Renderable = struct {
13 material: Material,
14 // The compiler inserts some padding here to ensure Mesh is correctly aligned.
15 mesh: Mesh,
16};
17
18var renderable: Renderable = undefined;
19
20test "assignment of field with padding" {
21 renderable = Renderable{
22 .mesh = Mesh{ .id = 0 },
23 .material = Material{
24 .transparent = false,
25 .emits_shadows = false,
26 },
27 };
28 try testing.expectEqual(false, renderable.material.transparent);
29 try testing.expectEqual(false, renderable.material.emits_shadows);
30 try testing.expectEqual(true, renderable.material.render_color);
31}
test/behavior/bugs/5413.zig created+6
...@@ -0,0 +1,6 @@
1const expect = @import("std").testing.expect;
2
3test "Peer type resolution with string literals and unknown length u8 pointers" {
4 try expect(@TypeOf("", "a", @as([*:0]const u8, "")) == [*:0]const u8);
5 try expect(@TypeOf(@as([*:0]const u8, "baz"), "foo", "bar") == [*:0]const u8);
6}
test/behavior/bugs/5474.zig created+57
...@@ -0,0 +1,57 @@
1const std = @import("std");
2
3// baseline (control) struct with array of scalar
4const Box0 = struct {
5 items: [4]Item,
6
7 const Item = struct {
8 num: u32,
9 };
10};
11
12// struct with array of empty struct
13const Box1 = struct {
14 items: [4]Item,
15
16 const Item = struct {};
17};
18
19// struct with array of zero-size struct
20const Box2 = struct {
21 items: [4]Item,
22
23 const Item = struct {
24 nothing: void,
25 };
26};
27
28fn doTest() !void {
29 // var
30 {
31 var box0: Box0 = .{ .items = undefined };
32 try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == false);
33
34 var box1: Box1 = .{ .items = undefined };
35 try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == false);
36
37 var box2: Box2 = .{ .items = undefined };
38 try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == false);
39 }
40
41 // const
42 {
43 const box0: Box0 = .{ .items = undefined };
44 try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == true);
45
46 const box1: Box1 = .{ .items = undefined };
47 try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == true);
48
49 const box2: Box2 = .{ .items = undefined };
50 try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == true);
51 }
52}
53
54test "pointer-to-array constness for zero-size elements" {
55 try doTest();
56 comptime try doTest();
57}
test/behavior/bugs/5487.zig created+12
...@@ -0,0 +1,12 @@
1const io = @import("std").io;
2
3pub fn write(_: void, bytes: []const u8) !usize {
4 return 0;
5}
6pub fn writer() io.Writer(void, @typeInfo(@typeInfo(@TypeOf(write)).Fn.return_type.?).ErrorUnion.error_set, write) {
7 return io.Writer(void, @typeInfo(@typeInfo(@TypeOf(write)).Fn.return_type.?).ErrorUnion.error_set, write){ .context = {} };
8}
9
10test "crash" {
11 _ = io.multiWriter(.{writer()});
12}
test/behavior/bugs/624.zig created+23
...@@ -0,0 +1,23 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const TestContext = struct {
5 server_context: *ListenerContext,
6};
7
8const ListenerContext = struct {
9 context_alloc: *ContextAllocator,
10};
11
12const ContextAllocator = MemoryPool(TestContext);
13
14fn MemoryPool(comptime T: type) type {
15 return struct {
16 n: usize,
17 };
18}
19
20test "foo" {
21 var allocator = ContextAllocator{ .n = 10 };
22 try expect(allocator.n == 10);
23}
test/behavior/bugs/6456.zig created+42
...@@ -0,0 +1,42 @@
1const std = @import("std");
2const testing = std.testing;
3const StructField = std.builtin.TypeInfo.StructField;
4const Declaration = std.builtin.TypeInfo.Declaration;
5
6const text =
7 \\f1
8 \\f2
9 \\f3
10;
11
12test "issue 6456" {
13 comptime {
14 var fields: []const StructField = &[0]StructField{};
15
16 var it = std.mem.tokenize(text, "\n");
17 while (it.next()) |name| {
18 fields = fields ++ &[_]StructField{StructField{
19 .alignment = 0,
20 .name = name,
21 .field_type = usize,
22 .default_value = @as(?usize, null),
23 .is_comptime = false,
24 }};
25 }
26
27 const T = @Type(.{
28 .Struct = .{
29 .layout = .Auto,
30 .is_tuple = false,
31 .fields = fields,
32 .decls = &[_]Declaration{},
33 },
34 });
35
36 const gen_fields = @typeInfo(T).Struct.fields;
37 try testing.expectEqual(3, gen_fields.len);
38 try testing.expectEqualStrings("f1", gen_fields[0].name);
39 try testing.expectEqualStrings("f2", gen_fields[1].name);
40 try testing.expectEqualStrings("f3", gen_fields[2].name);
41 }
42}
test/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 try std.testing.expect(@TypeOf(&x) == *const other_file.Integer);
7 try foo(&x);
8}
9
10fn foo(x: *const other_file.Integer) !void {
11 try std.testing.expect(x.* == 1234);
12}
test/behavior/bugs/655_other_file.zig created+1
...@@ -0,0 +1 @@
1pub const Integer = u32;
test/behavior/bugs/656.zig created+31
...@@ -0,0 +1,31 @@
1const expect = @import("std").testing.expect;
2
3const PrefixOp = union(enum) {
4 Return,
5 AddrOf: Value,
6};
7
8const Value = struct {
9 align_expr: ?u32,
10};
11
12test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {
13 try 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 try expect(align_expr == 1234);
26 }
27 },
28 PrefixOp.Return => {},
29 }
30 }
31}
test/behavior/bugs/6781.zig created+74
...@@ -0,0 +1,74 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4const segfault = true;
5
6pub const JournalHeader = packed struct {
7 hash_chain_root: u128 = undefined,
8 prev_hash_chain_root: u128,
9 checksum: u128 = undefined,
10 magic: u64,
11 command: u32,
12 size: u32,
13
14 pub fn calculate_checksum(self: *const JournalHeader, entry: []const u8) u128 {
15 assert(entry.len >= @sizeOf(JournalHeader));
16 assert(entry.len == self.size);
17
18 const checksum_offset = @byteOffsetOf(JournalHeader, "checksum");
19 const checksum_size = @sizeOf(@TypeOf(self.checksum));
20 assert(checksum_offset == 0 + 16 + 16);
21 assert(checksum_size == 16);
22
23 var target: [32]u8 = undefined;
24 std.crypto.hash.Blake3.hash(entry[checksum_offset + checksum_size ..], target[0..], .{});
25 return @bitCast(u128, target[0..checksum_size].*);
26 }
27
28 pub fn calculate_hash_chain_root(self: *const JournalHeader) u128 {
29 const hash_chain_root_size = @sizeOf(@TypeOf(self.hash_chain_root));
30 assert(hash_chain_root_size == 16);
31
32 const prev_hash_chain_root_offset = @byteOffsetOf(JournalHeader, "prev_hash_chain_root");
33 const prev_hash_chain_root_size = @sizeOf(@TypeOf(self.prev_hash_chain_root));
34 assert(prev_hash_chain_root_offset == 0 + 16);
35 assert(prev_hash_chain_root_size == 16);
36
37 const checksum_offset = @byteOffsetOf(JournalHeader, "checksum");
38 const checksum_size = @sizeOf(@TypeOf(self.checksum));
39 assert(checksum_offset == 0 + 16 + 16);
40 assert(checksum_size == 16);
41
42 assert(prev_hash_chain_root_offset + prev_hash_chain_root_size == checksum_offset);
43
44 const header = @bitCast([@sizeOf(JournalHeader)]u8, self.*);
45 const source = header[prev_hash_chain_root_offset .. checksum_offset + checksum_size];
46 assert(source.len == prev_hash_chain_root_size + checksum_size);
47 var target: [32]u8 = undefined;
48 std.crypto.hash.Blake3.hash(source, target[0..], .{});
49 if (segfault) {
50 return @bitCast(u128, target[0..hash_chain_root_size].*);
51 } else {
52 var array = target[0..hash_chain_root_size].*;
53 return @bitCast(u128, array);
54 }
55 }
56
57 pub fn set_checksum_and_hash_chain_root(self: *JournalHeader, entry: []const u8) void {
58 self.checksum = self.calculate_checksum(entry);
59 self.hash_chain_root = self.calculate_hash_chain_root();
60 }
61};
62
63test "fixed" {
64 var buffer = [_]u8{0} ** 65536;
65 var entry = std.mem.bytesAsValue(JournalHeader, buffer[0..@sizeOf(JournalHeader)]);
66 entry.* = .{
67 .prev_hash_chain_root = 0,
68 .magic = 0,
69 .command = 0,
70 .size = 64 + 128,
71 };
72 entry.set_checksum_and_hash_chain_root(buffer[0..entry.size]);
73 try std.io.null_writer.print("{}\n", .{entry});
74}
test/behavior/bugs/679.zig created+17
...@@ -0,0 +1,17 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4pub fn List(comptime T: type) type {
5 return u32;
6}
7
8const ElementList = List(Element);
9const Element = struct {
10 link: ElementList,
11};
12
13test "false dependency loop in struct definition" {
14 const listType = ElementList;
15 var x: listType = 42;
16 try expect(x == 42);
17}
test/behavior/bugs/6850.zig created+12
...@@ -0,0 +1,12 @@
1const std = @import("std");
2
3test "lazy sizeof comparison with zero" {
4 const Empty = struct {};
5 const T = *Empty;
6
7 try std.testing.expect(hasNoBits(T));
8}
9
10fn hasNoBits(comptime T: type) bool {
11 return @sizeOf(T) == 0;
12}
test/behavior/bugs/7003.zig created+8
...@@ -0,0 +1,8 @@
1test "@Type should resolve its children types" {
2 const sparse = enum(u2) { a, b, c };
3 const dense = enum(u2) { a, b, c, d };
4
5 comptime var sparse_info = @typeInfo(anyerror!sparse);
6 sparse_info.ErrorUnion.payload = dense;
7 const B = @Type(sparse_info);
8}
test/behavior/bugs/7027.zig created+17
...@@ -0,0 +1,17 @@
1const Foobar = struct {
2 myTypes: [128]type,
3 str: [1024]u8,
4
5 fn foo() @This() {
6 comptime var foobar: Foobar = undefined;
7 foobar.str = [_]u8{'a'} ** 1024;
8 return foobar;
9 }
10};
11
12fn foo(arg: anytype) void {}
13
14test "" {
15 comptime var foobar = Foobar.foo();
16 foo(foobar.str[0..10]);
17}
test/behavior/bugs/704.zig created+7
...@@ -0,0 +1,7 @@
1const xxx = struct {
2 pub fn bar(self: *xxx) void {}
3};
4test "bug 704" {
5 var x: xxx = undefined;
6 x.bar();
7}
test/behavior/bugs/7047.zig created+22
...@@ -0,0 +1,22 @@
1const std = @import("std");
2
3const U = union(enum) {
4 T: type,
5 N: void,
6};
7
8fn S(comptime query: U) type {
9 return struct {
10 fn tag() type {
11 return query.T;
12 }
13 };
14}
15
16test "compiler doesn't consider equal unions with different 'type' payload" {
17 const s1 = S(U{ .T = u32 }).tag();
18 try std.testing.expectEqual(u32, s1);
19
20 const s2 = S(U{ .T = u64 }).tag();
21 try std.testing.expectEqual(u64, s2);
22}
test/behavior/bugs/718.zig created+17
...@@ -0,0 +1,17 @@
1const std = @import("std");
2const mem = std.mem;
3const expect = std.testing.expect;
4const Keys = struct {
5 up: bool,
6 down: bool,
7 left: bool,
8 right: bool,
9};
10var keys: Keys = undefined;
11test "zero keys with @memset" {
12 @memset(@ptrCast([*]u8, &keys), 0, @sizeOf(@TypeOf(keys)));
13 try expect(!keys.up);
14 try expect(!keys.down);
15 try expect(!keys.left);
16 try expect(!keys.right);
17}
test/behavior/bugs/7250.zig created+15
...@@ -0,0 +1,15 @@
1const nrfx_uart_t = extern struct {
2 p_reg: [*c]u32,
3 drv_inst_idx: u8,
4};
5
6pub fn nrfx_uart_rx(p_instance: [*c]const nrfx_uart_t) void {}
7
8threadlocal var g_uart0 = nrfx_uart_t{
9 .p_reg = 0,
10 .drv_inst_idx = 0,
11};
12
13test "reference a global threadlocal variable" {
14 _ = nrfx_uart_rx(&g_uart0);
15}
test/behavior/bugs/726.zig created+15
...@@ -0,0 +1,15 @@
1const expect = @import("std").testing.expect;
2
3test "@ptrCast from const to nullable" {
4 const c: u8 = 4;
5 var x: ?*const u8 = @ptrCast(?*const u8, &c);
6 try expect(x.?.* == 4);
7}
8
9test "@ptrCast from var in empty struct to nullable" {
10 const container = struct {
11 var c: u8 = 4;
12 };
13 var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
14 try expect(x.?.* == 4);
15}
test/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/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 try std.testing.expectEqual(NormalDist1.f[i], NormalDist.f[i]);
64 }
65}
test/behavior/byteswap.zig created+68
...@@ -0,0 +1,68 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "@byteSwap integers" {
5 const ByteSwapIntTest = struct {
6 fn run() !void {
7 try t(u0, 0, 0);
8 try t(u8, 0x12, 0x12);
9 try t(u16, 0x1234, 0x3412);
10 try t(u24, 0x123456, 0x563412);
11 try t(u32, 0x12345678, 0x78563412);
12 try t(u40, 0x123456789a, 0x9a78563412);
13 try t(i48, 0x123456789abc, @bitCast(i48, @as(u48, 0xbc9a78563412)));
14 try t(u56, 0x123456789abcde, 0xdebc9a78563412);
15 try t(u64, 0x123456789abcdef1, 0xf1debc9a78563412);
16 try t(u128, 0x123456789abcdef11121314151617181, 0x8171615141312111f1debc9a78563412);
17
18 try t(u0, @as(u0, 0), 0);
19 try t(i8, @as(i8, -50), -50);
20 try t(i16, @bitCast(i16, @as(u16, 0x1234)), @bitCast(i16, @as(u16, 0x3412)));
21 try t(i24, @bitCast(i24, @as(u24, 0x123456)), @bitCast(i24, @as(u24, 0x563412)));
22 try t(i32, @bitCast(i32, @as(u32, 0x12345678)), @bitCast(i32, @as(u32, 0x78563412)));
23 try t(u40, @bitCast(i40, @as(u40, 0x123456789a)), @as(u40, 0x9a78563412));
24 try t(i48, @bitCast(i48, @as(u48, 0x123456789abc)), @bitCast(i48, @as(u48, 0xbc9a78563412)));
25 try t(i56, @bitCast(i56, @as(u56, 0x123456789abcde)), @bitCast(i56, @as(u56, 0xdebc9a78563412)));
26 try t(i64, @bitCast(i64, @as(u64, 0x123456789abcdef1)), @bitCast(i64, @as(u64, 0xf1debc9a78563412)));
27 try t(
28 i128,
29 @bitCast(i128, @as(u128, 0x123456789abcdef11121314151617181)),
30 @bitCast(i128, @as(u128, 0x8171615141312111f1debc9a78563412)),
31 );
32 }
33 fn t(comptime I: type, input: I, expected_output: I) !void {
34 try std.testing.expectEqual(expected_output, @byteSwap(I, input));
35 }
36 };
37 comptime try ByteSwapIntTest.run();
38 try ByteSwapIntTest.run();
39}
40
41test "@byteSwap vectors" {
42 // https://github.com/ziglang/zig/issues/3563
43 if (std.Target.current.os.tag == .dragonfly) return error.SkipZigTest;
44
45 // https://github.com/ziglang/zig/issues/3317
46 if (std.Target.current.cpu.arch == .mipsel or std.Target.current.cpu.arch == .mips) return error.SkipZigTest;
47
48 const ByteSwapVectorTest = struct {
49 fn run() !void {
50 try t(u8, 2, [_]u8{ 0x12, 0x13 }, [_]u8{ 0x12, 0x13 });
51 try t(u16, 2, [_]u16{ 0x1234, 0x2345 }, [_]u16{ 0x3412, 0x4523 });
52 try t(u24, 2, [_]u24{ 0x123456, 0x234567 }, [_]u24{ 0x563412, 0x674523 });
53 }
54
55 fn t(
56 comptime I: type,
57 comptime n: comptime_int,
58 input: std.meta.Vector(n, I),
59 expected_vector: std.meta.Vector(n, I),
60 ) !void {
61 const actual_output: [n]I = @byteSwap(I, input);
62 const expected_output: [n]I = expected_vector;
63 try std.testing.expectEqual(expected_output, actual_output);
64 }
65 };
66 comptime try ByteSwapVectorTest.run();
67 try ByteSwapVectorTest.run();
68}
test/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 try std.testing.expect(std.mem.eql(u8, result, "string literal"));
10}
11
12fn start() void {
13 foo("string literal");
14}
15
16fn foo(x: anytype) void {
17 bar(x);
18}
19
20fn bar(x: anytype) void {
21 result = x;
22}
23
24fn blowUpStack(x: u32) void {
25 if (x == 0) return;
26 blowUpStack(x - 1);
27}
test/behavior/call.zig created+74
...@@ -0,0 +1,74 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4
5test "basic invocations" {
6 const foo = struct {
7 fn foo() i32 {
8 return 1234;
9 }
10 }.foo;
11 try expect(@call(.{}, foo, .{}) == 1234);
12 comptime {
13 // modifiers that allow comptime calls
14 try expect(@call(.{}, foo, .{}) == 1234);
15 try expect(@call(.{ .modifier = .no_async }, foo, .{}) == 1234);
16 try expect(@call(.{ .modifier = .always_tail }, foo, .{}) == 1234);
17 try expect(@call(.{ .modifier = .always_inline }, foo, .{}) == 1234);
18 }
19 {
20 // comptime call without comptime keyword
21 const result = @call(.{ .modifier = .compile_time }, foo, .{}) == 1234;
22 comptime try expect(result);
23 }
24 {
25 // call of non comptime-known function
26 var alias_foo = foo;
27 try expect(@call(.{ .modifier = .no_async }, alias_foo, .{}) == 1234);
28 try expect(@call(.{ .modifier = .never_tail }, alias_foo, .{}) == 1234);
29 try expect(@call(.{ .modifier = .never_inline }, alias_foo, .{}) == 1234);
30 }
31}
32
33test "tuple parameters" {
34 const add = struct {
35 fn add(a: i32, b: i32) i32 {
36 return a + b;
37 }
38 }.add;
39 var a: i32 = 12;
40 var b: i32 = 34;
41 try expect(@call(.{}, add, .{ a, 34 }) == 46);
42 try expect(@call(.{}, add, .{ 12, b }) == 46);
43 try expect(@call(.{}, add, .{ a, b }) == 46);
44 try expect(@call(.{}, add, .{ 12, 34 }) == 46);
45 comptime try expect(@call(.{}, add, .{ 12, 34 }) == 46);
46 {
47 const separate_args0 = .{ a, b };
48 const separate_args1 = .{ a, 34 };
49 const separate_args2 = .{ 12, 34 };
50 const separate_args3 = .{ 12, b };
51 try expect(@call(.{ .modifier = .always_inline }, add, separate_args0) == 46);
52 try expect(@call(.{ .modifier = .always_inline }, add, separate_args1) == 46);
53 try expect(@call(.{ .modifier = .always_inline }, add, separate_args2) == 46);
54 try expect(@call(.{ .modifier = .always_inline }, add, separate_args3) == 46);
55 }
56}
57
58test "comptime call with bound function as parameter" {
59 const S = struct {
60 fn ReturnType(func: anytype) type {
61 return switch (@typeInfo(@TypeOf(func))) {
62 .BoundFn => |info| info,
63 else => unreachable,
64 }.return_type orelse void;
65 }
66
67 fn call_me_maybe() ?i32 {
68 return 123;
69 }
70 };
71
72 var inst: S = undefined;
73 try expectEqual(?i32, S.ReturnType(inst.call_me_maybe));
74}
test/behavior/cast.zig created+927
...@@ -0,0 +1,927 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4const maxInt = std.math.maxInt;
5const Vector = std.meta.Vector;
6const native_endian = @import("builtin").target.cpu.arch.endian();
7
8test "int to ptr cast" {
9 const x = @as(usize, 13);
10 const y = @intToPtr(*u8, x);
11 const z = @ptrToInt(y);
12 try expect(z == 13);
13}
14
15test "integer literal to pointer cast" {
16 const vga_mem = @intToPtr(*u16, 0xB8000);
17 try expect(@ptrToInt(vga_mem) == 0xB8000);
18}
19
20test "pointer reinterpret const float to int" {
21 // The hex representation is 0x3fe3333333333303.
22 const float: f64 = 5.99999999999994648725e-01;
23 const float_ptr = &float;
24 const int_ptr = @ptrCast(*const i32, float_ptr);
25 const int_val = int_ptr.*;
26 if (native_endian == .Little)
27 try expect(int_val == 0x33333303)
28 else
29 try expect(int_val == 0x3fe33333);
30}
31
32test "implicitly cast indirect pointer to maybe-indirect pointer" {
33 const S = struct {
34 const Self = @This();
35 x: u8,
36 fn constConst(p: *const *const Self) u8 {
37 return p.*.x;
38 }
39 fn maybeConstConst(p: ?*const *const Self) u8 {
40 return p.?.*.x;
41 }
42 fn constConstConst(p: *const *const *const Self) u8 {
43 return p.*.*.x;
44 }
45 fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
46 return p.?.*.*.x;
47 }
48 };
49 const s = S{ .x = 42 };
50 const p = &s;
51 const q = &p;
52 const r = &q;
53 try expect(42 == S.constConst(q));
54 try expect(42 == S.maybeConstConst(q));
55 try expect(42 == S.constConstConst(r));
56 try expect(42 == S.maybeConstConstConst(r));
57}
58
59test "explicit cast from integer to error type" {
60 try testCastIntToErr(error.ItBroke);
61 comptime try testCastIntToErr(error.ItBroke);
62}
63fn testCastIntToErr(err: anyerror) !void {
64 const x = @errorToInt(err);
65 const y = @intToError(x);
66 try expect(error.ItBroke == y);
67}
68
69test "peer resolve arrays of different size to const slice" {
70 try expect(mem.eql(u8, boolToStr(true), "true"));
71 try expect(mem.eql(u8, boolToStr(false), "false"));
72 comptime try expect(mem.eql(u8, boolToStr(true), "true"));
73 comptime try expect(mem.eql(u8, boolToStr(false), "false"));
74}
75fn boolToStr(b: bool) []const u8 {
76 return if (b) "true" else "false";
77}
78
79test "peer resolve array and const slice" {
80 try testPeerResolveArrayConstSlice(true);
81 comptime try testPeerResolveArrayConstSlice(true);
82}
83fn testPeerResolveArrayConstSlice(b: bool) !void {
84 const value1 = if (b) "aoeu" else @as([]const u8, "zz");
85 const value2 = if (b) @as([]const u8, "zz") else "aoeu";
86 try expect(mem.eql(u8, value1, "aoeu"));
87 try expect(mem.eql(u8, value2, "zz"));
88}
89
90test "implicitly cast from T to anyerror!?T" {
91 try castToOptionalTypeError(1);
92 comptime try castToOptionalTypeError(1);
93}
94
95const A = struct {
96 a: i32,
97};
98fn castToOptionalTypeError(z: i32) !void {
99 const x = @as(i32, 1);
100 const y: anyerror!?i32 = x;
101 try expect((try y).? == 1);
102
103 const f = z;
104 const g: anyerror!?i32 = f;
105
106 const a = A{ .a = z };
107 const b: anyerror!?A = a;
108 try expect((b catch unreachable).?.a == 1);
109}
110
111test "implicitly cast from int to anyerror!?T" {
112 implicitIntLitToOptional();
113 comptime implicitIntLitToOptional();
114}
115fn implicitIntLitToOptional() void {
116 const f: ?i32 = 1;
117 const g: anyerror!?i32 = 1;
118}
119
120test "return null from fn() anyerror!?&T" {
121 const a = returnNullFromOptionalTypeErrorRef();
122 const b = returnNullLitFromOptionalTypeErrorRef();
123 try expect((try a) == null and (try b) == null);
124}
125fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
126 const a: ?*A = null;
127 return a;
128}
129fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
130 return null;
131}
132
133test "peer type resolution: ?T and T" {
134 try expect(peerTypeTAndOptionalT(true, false).? == 0);
135 try expect(peerTypeTAndOptionalT(false, false).? == 3);
136 comptime {
137 try expect(peerTypeTAndOptionalT(true, false).? == 0);
138 try expect(peerTypeTAndOptionalT(false, false).? == 3);
139 }
140}
141fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
142 if (c) {
143 return if (b) null else @as(usize, 0);
144 }
145
146 return @as(usize, 3);
147}
148
149test "peer type resolution: [0]u8 and []const u8" {
150 try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
151 try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
152 comptime {
153 try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
154 try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
155 }
156}
157fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
158 if (a) {
159 return &[_]u8{};
160 }
161
162 return slice[0..1];
163}
164
165test "implicitly cast from [N]T to ?[]const T" {
166 try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
167 comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
168}
169
170fn castToOptionalSlice() ?[]const u8 {
171 return "hi";
172}
173
174test "implicitly cast from [0]T to anyerror![]T" {
175 try testCastZeroArrayToErrSliceMut();
176 comptime try testCastZeroArrayToErrSliceMut();
177}
178
179fn testCastZeroArrayToErrSliceMut() !void {
180 try expect((gimmeErrOrSlice() catch unreachable).len == 0);
181}
182
183fn gimmeErrOrSlice() anyerror![]u8 {
184 return &[_]u8{};
185}
186
187test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
188 const S = struct {
189 fn doTheTest() anyerror!void {
190 {
191 var data = "hi".*;
192 const slice = data[0..];
193 try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
194 try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
195 }
196 {
197 var data: [2]u8 = "hi".*;
198 const slice = data[0..];
199 try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
200 try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
201 }
202 }
203 };
204 try S.doTheTest();
205 comptime try S.doTheTest();
206}
207fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
208 if (a) {
209 return &[_]u8{};
210 }
211
212 return slice[0..1];
213}
214
215test "resolve undefined with integer" {
216 try testResolveUndefWithInt(true, 1234);
217 comptime try testResolveUndefWithInt(true, 1234);
218}
219fn testResolveUndefWithInt(b: bool, x: i32) !void {
220 const value = if (b) x else undefined;
221 if (b) {
222 try expect(value == x);
223 }
224}
225
226test "implicit cast from &const [N]T to []const T" {
227 try testCastConstArrayRefToConstSlice();
228 comptime try testCastConstArrayRefToConstSlice();
229}
230
231fn testCastConstArrayRefToConstSlice() !void {
232 {
233 const blah = "aoeu".*;
234 const const_array_ref = &blah;
235 try expect(@TypeOf(const_array_ref) == *const [4:0]u8);
236 const slice: []const u8 = const_array_ref;
237 try expect(mem.eql(u8, slice, "aoeu"));
238 }
239 {
240 const blah: [4]u8 = "aoeu".*;
241 const const_array_ref = &blah;
242 try expect(@TypeOf(const_array_ref) == *const [4]u8);
243 const slice: []const u8 = const_array_ref;
244 try expect(mem.eql(u8, slice, "aoeu"));
245 }
246}
247
248test "peer type resolution: error and [N]T" {
249 try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
250 comptime try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
251 try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
252 comptime try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
253}
254
255fn testPeerErrorAndArray(x: u8) anyerror![]const u8 {
256 return switch (x) {
257 0x00 => "OK",
258 else => error.BadValue,
259 };
260}
261fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
262 return switch (x) {
263 0x00 => "OK",
264 0x01 => "OKK",
265 else => error.BadValue,
266 };
267}
268
269test "@floatToInt" {
270 try testFloatToInts();
271 comptime try testFloatToInts();
272}
273
274fn testFloatToInts() !void {
275 const x = @as(i32, 1e4);
276 try expect(x == 10000);
277 const y = @floatToInt(i32, @as(f32, 1e4));
278 try expect(y == 10000);
279 try expectFloatToInt(f16, 255.1, u8, 255);
280 try expectFloatToInt(f16, 127.2, i8, 127);
281 try expectFloatToInt(f16, -128.2, i8, -128);
282 try expectFloatToInt(f32, 255.1, u8, 255);
283 try expectFloatToInt(f32, 127.2, i8, 127);
284 try expectFloatToInt(f32, -128.2, i8, -128);
285 try expectFloatToInt(comptime_int, 1234, i16, 1234);
286}
287
288fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
289 try expect(@floatToInt(I, f) == i);
290}
291
292test "cast u128 to f128 and back" {
293 comptime try testCast128();
294 try testCast128();
295}
296
297fn testCast128() !void {
298 try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
299}
300
301fn cast128Int(x: f128) u128 {
302 return @bitCast(u128, x);
303}
304
305fn cast128Float(x: u128) f128 {
306 return @bitCast(f128, x);
307}
308
309test "single-item pointer of array to slice and to unknown length pointer" {
310 try testCastPtrOfArrayToSliceAndPtr();
311 comptime try testCastPtrOfArrayToSliceAndPtr();
312}
313
314fn testCastPtrOfArrayToSliceAndPtr() !void {
315 {
316 var array = "aoeu".*;
317 const x: [*]u8 = &array;
318 x[0] += 1;
319 try expect(mem.eql(u8, array[0..], "boeu"));
320 const y: []u8 = &array;
321 y[0] += 1;
322 try expect(mem.eql(u8, array[0..], "coeu"));
323 }
324 {
325 var array: [4]u8 = "aoeu".*;
326 const x: [*]u8 = &array;
327 x[0] += 1;
328 try expect(mem.eql(u8, array[0..], "boeu"));
329 const y: []u8 = &array;
330 y[0] += 1;
331 try expect(mem.eql(u8, array[0..], "coeu"));
332 }
333}
334
335test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
336 const window_name = [1][*]const u8{"window name"};
337 const x: [*]const ?[*]const u8 = &window_name;
338 try expect(mem.eql(u8, std.mem.spanZ(@ptrCast([*:0]const u8, x[0].?)), "window name"));
339}
340
341test "@intCast comptime_int" {
342 const result = @intCast(i32, 1234);
343 try expect(@TypeOf(result) == i32);
344 try expect(result == 1234);
345}
346
347test "@floatCast comptime_int and comptime_float" {
348 {
349 const result = @floatCast(f16, 1234);
350 try expect(@TypeOf(result) == f16);
351 try expect(result == 1234.0);
352 }
353 {
354 const result = @floatCast(f16, 1234.0);
355 try expect(@TypeOf(result) == f16);
356 try expect(result == 1234.0);
357 }
358 {
359 const result = @floatCast(f32, 1234);
360 try expect(@TypeOf(result) == f32);
361 try expect(result == 1234.0);
362 }
363 {
364 const result = @floatCast(f32, 1234.0);
365 try expect(@TypeOf(result) == f32);
366 try expect(result == 1234.0);
367 }
368}
369
370test "vector casts" {
371 const S = struct {
372 fn doTheTest() !void {
373 // Upcast (implicit, equivalent to @intCast)
374 var up0: Vector(2, u8) = [_]u8{ 0x55, 0xaa };
375 var up1 = @as(Vector(2, u16), up0);
376 var up2 = @as(Vector(2, u32), up0);
377 var up3 = @as(Vector(2, u64), up0);
378 // Downcast (safety-checked)
379 var down0 = up3;
380 var down1 = @intCast(Vector(2, u32), down0);
381 var down2 = @intCast(Vector(2, u16), down0);
382 var down3 = @intCast(Vector(2, u8), down0);
383
384 try expect(mem.eql(u16, &@as([2]u16, up1), &[2]u16{ 0x55, 0xaa }));
385 try expect(mem.eql(u32, &@as([2]u32, up2), &[2]u32{ 0x55, 0xaa }));
386 try expect(mem.eql(u64, &@as([2]u64, up3), &[2]u64{ 0x55, 0xaa }));
387
388 try expect(mem.eql(u32, &@as([2]u32, down1), &[2]u32{ 0x55, 0xaa }));
389 try expect(mem.eql(u16, &@as([2]u16, down2), &[2]u16{ 0x55, 0xaa }));
390 try expect(mem.eql(u8, &@as([2]u8, down3), &[2]u8{ 0x55, 0xaa }));
391 }
392
393 fn doTheTestFloat() !void {
394 var vec = @splat(2, @as(f32, 1234.0));
395 var wider: Vector(2, f64) = vec;
396 try expect(wider[0] == 1234.0);
397 try expect(wider[1] == 1234.0);
398 }
399 };
400
401 try S.doTheTest();
402 comptime try S.doTheTest();
403 try S.doTheTestFloat();
404 comptime try S.doTheTestFloat();
405}
406
407test "comptime_int @intToFloat" {
408 {
409 const result = @intToFloat(f16, 1234);
410 try expect(@TypeOf(result) == f16);
411 try expect(result == 1234.0);
412 }
413 {
414 const result = @intToFloat(f32, 1234);
415 try expect(@TypeOf(result) == f32);
416 try expect(result == 1234.0);
417 }
418 {
419 const result = @intToFloat(f64, 1234);
420 try expect(@TypeOf(result) == f64);
421 try expect(result == 1234.0);
422 }
423 {
424 const result = @intToFloat(f128, 1234);
425 try expect(@TypeOf(result) == f128);
426 try expect(result == 1234.0);
427 }
428 // big comptime_int (> 64 bits) to f128 conversion
429 {
430 const result = @intToFloat(f128, 0x1_0000_0000_0000_0000);
431 try expect(@TypeOf(result) == f128);
432 try expect(result == 0x1_0000_0000_0000_0000.0);
433 }
434}
435
436test "@intCast i32 to u7" {
437 var x: u128 = maxInt(u128);
438 var y: i32 = 120;
439 var z = x >> @intCast(u7, y);
440 try expect(z == 0xff);
441}
442
443test "@floatCast cast down" {
444 {
445 var double: f64 = 0.001534;
446 var single = @floatCast(f32, double);
447 try expect(single == 0.001534);
448 }
449 {
450 const double: f64 = 0.001534;
451 const single = @floatCast(f32, double);
452 try expect(single == 0.001534);
453 }
454}
455
456test "implicit cast undefined to optional" {
457 try expect(MakeType(void).getNull() == null);
458 try expect(MakeType(void).getNonNull() != null);
459}
460
461fn MakeType(comptime T: type) type {
462 return struct {
463 fn getNull() ?T {
464 return null;
465 }
466
467 fn getNonNull() ?T {
468 return @as(T, undefined);
469 }
470 };
471}
472
473test "implicit cast from *[N]T to ?[*]T" {
474 var x: ?[*]u16 = null;
475 var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
476
477 x = &y;
478 try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
479 x.?[0] = 8;
480 y[3] = 6;
481 try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
482}
483
484test "implicit cast from *[N]T to [*c]T" {
485 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
486 var y: [*c]u16 = &x;
487
488 try expect(std.mem.eql(u16, x[0..4], y[0..4]));
489 x[0] = 8;
490 y[3] = 6;
491 try expect(std.mem.eql(u16, x[0..4], y[0..4]));
492}
493
494test "implicit cast from *T to ?*c_void" {
495 var a: u8 = 1;
496 incrementVoidPtrValue(&a);
497 try std.testing.expect(a == 2);
498}
499
500fn incrementVoidPtrValue(value: ?*c_void) void {
501 @ptrCast(*u8, value.?).* += 1;
502}
503
504test "implicit cast from [*]T to ?*c_void" {
505 var a = [_]u8{ 3, 2, 1 };
506 var runtime_zero: usize = 0;
507 incrementVoidPtrArray(a[runtime_zero..].ptr, 3);
508 try expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 }));
509}
510
511fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
512 var n: usize = 0;
513 while (n < len) : (n += 1) {
514 @ptrCast([*]u8, array.?)[n] += 1;
515 }
516}
517
518test "*usize to *void" {
519 var i = @as(usize, 0);
520 var v = @ptrCast(*void, &i);
521 v.* = {};
522}
523
524test "compile time int to ptr of function" {
525 try foobar(FUNCTION_CONSTANT);
526}
527
528pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
529pub const PFN_void = fn (*c_void) callconv(.C) void;
530
531fn foobar(func: PFN_void) !void {
532 try std.testing.expect(@ptrToInt(func) == maxInt(usize));
533}
534
535test "implicit ptr to *c_void" {
536 var a: u32 = 1;
537 var ptr: *align(@alignOf(u32)) c_void = &a;
538 var b: *u32 = @ptrCast(*u32, ptr);
539 try expect(b.* == 1);
540 var ptr2: ?*align(@alignOf(u32)) c_void = &a;
541 var c: *u32 = @ptrCast(*u32, ptr2.?);
542 try expect(c.* == 1);
543}
544
545test "@intCast to comptime_int" {
546 try expect(@intCast(comptime_int, 0) == 0);
547}
548
549test "implicit cast comptime numbers to any type when the value fits" {
550 const a: u64 = 255;
551 var b: u8 = a;
552 try expect(b == 255);
553}
554
555test "@intToEnum passed a comptime_int to an enum with one item" {
556 const E = enum {
557 A,
558 };
559 const x = @intToEnum(E, 0);
560 try expect(x == E.A);
561}
562
563test "@intToEnum runtime to an extern enum with duplicate values" {
564 const E = extern enum(u8) {
565 A = 1,
566 B = 1,
567 };
568 var a: u8 = 1;
569 var x = @intToEnum(E, a);
570 try expect(x == E.A);
571 try expect(x == E.B);
572}
573
574test "@intCast to u0 and use the result" {
575 const S = struct {
576 fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {
577 try expect((one << @intCast(u0, bigzero)) == 1);
578 try expect((zero << @intCast(u0, bigzero)) == 0);
579 }
580 };
581 try S.doTheTest(0, 1, 0);
582 comptime try S.doTheTest(0, 1, 0);
583}
584
585test "peer type resolution: unreachable, null, slice" {
586 const S = struct {
587 fn doTheTest(num: usize, word: []const u8) !void {
588 const result = switch (num) {
589 0 => null,
590 1 => word,
591 else => unreachable,
592 };
593 try expect(mem.eql(u8, result.?, "hi"));
594 }
595 };
596 try S.doTheTest(1, "hi");
597}
598
599test "peer type resolution: unreachable, error set, unreachable" {
600 const Error = error{
601 FileDescriptorAlreadyPresentInSet,
602 OperationCausesCircularLoop,
603 FileDescriptorNotRegistered,
604 SystemResources,
605 UserResourceLimitReached,
606 FileDescriptorIncompatibleWithEpoll,
607 Unexpected,
608 };
609 var err = Error.SystemResources;
610 const transformed_err = switch (err) {
611 error.FileDescriptorAlreadyPresentInSet => unreachable,
612 error.OperationCausesCircularLoop => unreachable,
613 error.FileDescriptorNotRegistered => unreachable,
614 error.SystemResources => error.SystemResources,
615 error.UserResourceLimitReached => error.UserResourceLimitReached,
616 error.FileDescriptorIncompatibleWithEpoll => unreachable,
617 error.Unexpected => unreachable,
618 };
619 try expect(transformed_err == error.SystemResources);
620}
621
622test "implicit cast comptime_int to comptime_float" {
623 comptime try expect(@as(comptime_float, 10) == @as(f32, 10));
624 try expect(2 == 2.0);
625}
626
627test "implicit cast *[0]T to E![]const u8" {
628 var x = @as(anyerror![]const u8, &[0]u8{});
629 try expect((x catch unreachable).len == 0);
630}
631
632test "peer cast *[0]T to E![]const T" {
633 var buffer: [5]u8 = "abcde".*;
634 var buf: anyerror![]const u8 = buffer[0..];
635 var b = false;
636 var y = if (b) &[0]u8{} else buf;
637 try expect(mem.eql(u8, "abcde", y catch unreachable));
638}
639
640test "peer cast *[0]T to []const T" {
641 var buffer: [5]u8 = "abcde".*;
642 var buf: []const u8 = buffer[0..];
643 var b = false;
644 var y = if (b) &[0]u8{} else buf;
645 try expect(mem.eql(u8, "abcde", y));
646}
647
648var global_array: [4]u8 = undefined;
649test "cast from array reference to fn" {
650 const f = @ptrCast(fn () callconv(.C) void, &global_array);
651 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
652}
653
654test "*const [N]null u8 to ?[]const u8" {
655 const S = struct {
656 fn doTheTest() !void {
657 var a = "Hello";
658 var b: ?[]const u8 = a;
659 try expect(mem.eql(u8, b.?, "Hello"));
660 }
661 };
662 try S.doTheTest();
663 comptime try S.doTheTest();
664}
665
666test "peer resolution of string literals" {
667 const S = struct {
668 const E = extern enum {
669 a,
670 b,
671 c,
672 d,
673 };
674
675 fn doTheTest(e: E) !void {
676 const cmd = switch (e) {
677 .a => "one",
678 .b => "two",
679 .c => "three",
680 .d => "four",
681 };
682 try expect(mem.eql(u8, cmd, "two"));
683 }
684 };
685 try S.doTheTest(.b);
686 comptime try S.doTheTest(.b);
687}
688
689test "type coercion related to sentinel-termination" {
690 const S = struct {
691 fn doTheTest() !void {
692 // [:x]T to []T
693 {
694 var array = [4:0]i32{ 1, 2, 3, 4 };
695 var slice: [:0]i32 = &array;
696 var dest: []i32 = slice;
697 try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
698 }
699
700 // [*:x]T to [*]T
701 {
702 var array = [4:99]i32{ 1, 2, 3, 4 };
703 var dest: [*]i32 = &array;
704 try expect(dest[0] == 1);
705 try expect(dest[1] == 2);
706 try expect(dest[2] == 3);
707 try expect(dest[3] == 4);
708 try expect(dest[4] == 99);
709 }
710
711 // [N:x]T to [N]T
712 {
713 var array = [4:0]i32{ 1, 2, 3, 4 };
714 var dest: [4]i32 = array;
715 try expect(mem.eql(i32, &dest, &[_]i32{ 1, 2, 3, 4 }));
716 }
717
718 // *[N:x]T to *[N]T
719 {
720 var array = [4:0]i32{ 1, 2, 3, 4 };
721 var dest: *[4]i32 = &array;
722 try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
723 }
724
725 // [:x]T to [*:x]T
726 {
727 var array = [4:0]i32{ 1, 2, 3, 4 };
728 var slice: [:0]i32 = &array;
729 var dest: [*:0]i32 = slice;
730 try expect(dest[0] == 1);
731 try expect(dest[1] == 2);
732 try expect(dest[2] == 3);
733 try expect(dest[3] == 4);
734 try expect(dest[4] == 0);
735 }
736 }
737 };
738 try S.doTheTest();
739 comptime try S.doTheTest();
740}
741
742test "cast i8 fn call peers to i32 result" {
743 const S = struct {
744 fn doTheTest() !void {
745 var cond = true;
746 const value: i32 = if (cond) smallBoi() else bigBoi();
747 try expect(value == 123);
748 }
749 fn smallBoi() i8 {
750 return 123;
751 }
752 fn bigBoi() i16 {
753 return 1234;
754 }
755 };
756 try S.doTheTest();
757 comptime try S.doTheTest();
758}
759
760test "return u8 coercing into ?u32 return type" {
761 const S = struct {
762 fn doTheTest() !void {
763 try expect(foo(123).? == 123);
764 }
765 fn foo(arg: u8) ?u32 {
766 return arg;
767 }
768 };
769 try S.doTheTest();
770 comptime try S.doTheTest();
771}
772
773test "peer result null and comptime_int" {
774 const S = struct {
775 fn blah(n: i32) ?i32 {
776 if (n == 0) {
777 return null;
778 } else if (n < 0) {
779 return -1;
780 } else {
781 return 1;
782 }
783 }
784 };
785
786 try expect(S.blah(0) == null);
787 comptime try expect(S.blah(0) == null);
788 try expect(S.blah(10).? == 1);
789 comptime try expect(S.blah(10).? == 1);
790 try expect(S.blah(-10).? == -1);
791 comptime try expect(S.blah(-10).? == -1);
792}
793
794test "peer type resolution implicit cast to return type" {
795 const S = struct {
796 fn doTheTest() !void {
797 for ("hello") |c| _ = f(c);
798 }
799 fn f(c: u8) []const u8 {
800 return switch (c) {
801 'h', 'e' => &[_]u8{c}, // should cast to slice
802 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
803 else => ([_]u8{c})[0..], // is a slice
804 };
805 }
806 };
807 try S.doTheTest();
808 comptime try S.doTheTest();
809}
810
811test "peer type resolution implicit cast to variable type" {
812 const S = struct {
813 fn doTheTest() !void {
814 var x: []const u8 = undefined;
815 for ("hello") |c| x = switch (c) {
816 'h', 'e' => &[_]u8{c}, // should cast to slice
817 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
818 else => ([_]u8{c})[0..], // is a slice
819 };
820 }
821 };
822 try S.doTheTest();
823 comptime try S.doTheTest();
824}
825
826test "variable initialization uses result locations properly with regards to the type" {
827 var b = true;
828 const x: i32 = if (b) 1 else 2;
829 try expect(x == 1);
830}
831
832test "cast between [*c]T and ?[*:0]T on fn parameter" {
833 const S = struct {
834 const Handler = ?fn ([*c]const u8) callconv(.C) void;
835 fn addCallback(handler: Handler) void {}
836
837 fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void {}
838
839 fn doTheTest() void {
840 addCallback(myCallback);
841 }
842 };
843 S.doTheTest();
844}
845
846test "cast between C pointer with different but compatible types" {
847 const S = struct {
848 fn foo(arg: [*]c_ushort) u16 {
849 return arg[0];
850 }
851 fn doTheTest() !void {
852 var x = [_]u16{ 4, 2, 1, 3 };
853 try expect(foo(@ptrCast([*]u16, &x)) == 4);
854 }
855 };
856 try S.doTheTest();
857}
858
859var global_struct: struct { f0: usize } = undefined;
860
861test "assignment to optional pointer result loc" {
862 var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
863 try expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
864}
865
866test "peer type resolve string lit with sentinel-terminated mutable slice" {
867 var array: [4:0]u8 = undefined;
868 array[4] = 0; // TODO remove this when #4372 is solved
869 var slice: [:0]u8 = array[0..4 :0];
870 comptime try expect(@TypeOf(slice, "hi") == [:0]const u8);
871 comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
872}
873
874test "peer type unsigned int to signed" {
875 var w: u31 = 5;
876 var x: u8 = 7;
877 var y: i32 = -5;
878 var a = w + y + x;
879 comptime try expect(@TypeOf(a) == i32);
880 try expect(a == 7);
881}
882
883test "peer type resolve array pointers, one of them const" {
884 var array1: [4]u8 = undefined;
885 const array2: [5]u8 = undefined;
886 comptime try expect(@TypeOf(&array1, &array2) == []const u8);
887 comptime try expect(@TypeOf(&array2, &array1) == []const u8);
888}
889
890test "peer type resolve array pointer and unknown pointer" {
891 const const_array: [4]u8 = undefined;
892 var array: [4]u8 = undefined;
893 var const_ptr: [*]const u8 = undefined;
894 var ptr: [*]u8 = undefined;
895
896 comptime try expect(@TypeOf(&array, ptr) == [*]u8);
897 comptime try expect(@TypeOf(ptr, &array) == [*]u8);
898
899 comptime try expect(@TypeOf(&const_array, ptr) == [*]const u8);
900 comptime try expect(@TypeOf(ptr, &const_array) == [*]const u8);
901
902 comptime try expect(@TypeOf(&array, const_ptr) == [*]const u8);
903 comptime try expect(@TypeOf(const_ptr, &array) == [*]const u8);
904
905 comptime try expect(@TypeOf(&const_array, const_ptr) == [*]const u8);
906 comptime try expect(@TypeOf(const_ptr, &const_array) == [*]const u8);
907}
908
909test "comptime float casts" {
910 const a = @intToFloat(comptime_float, 1);
911 try expect(a == 1);
912 try expect(@TypeOf(a) == comptime_float);
913 const b = @floatToInt(comptime_int, 2);
914 try expect(b == 2);
915 try expect(@TypeOf(b) == comptime_int);
916}
917
918test "cast from ?[*]T to ??[*]T" {
919 const a: ??[*]u8 = @as(?[*]u8, null);
920 try expect(a != null and a.? == null);
921}
922
923test "cast between *[N]void and []void" {
924 var a: [4]void = undefined;
925 var b: []void = &a;
926 try expect(b.len == 4);
927}
test/behavior/const_slice_child.zig created+47
...@@ -0,0 +1,47 @@
1const std = @import("std");
2const debug = std.debug;
3const testing = std.testing;
4const expect = testing.expect;
5
6var argv: [*]const [*]const u8 = undefined;
7
8test "const slice child" {
9 const strs = [_][*]const u8{
10 "one",
11 "two",
12 "three",
13 };
14 argv = &strs;
15 try bar(strs.len);
16}
17
18fn foo(args: [][]const u8) !void {
19 try expect(args.len == 3);
20 try expect(streql(args[0], "one"));
21 try expect(streql(args[1], "two"));
22 try expect(streql(args[2], "three"));
23}
24
25fn bar(argc: usize) !void {
26 const args = testing.allocator.alloc([]const u8, argc) catch unreachable;
27 defer testing.allocator.free(args);
28 for (args) |_, i| {
29 const ptr = argv[i];
30 args[i] = ptr[0..strlen(ptr)];
31 }
32 try foo(args);
33}
34
35fn strlen(ptr: [*]const u8) usize {
36 var count: usize = 0;
37 while (ptr[count] != 0) : (count += 1) {}
38 return count;
39}
40
41fn streql(a: []const u8, b: []const u8) bool {
42 if (a.len != b.len) return false;
43 for (a) |item, index| {
44 if (b[index] != item) return false;
45 }
46 return true;
47}
test/behavior/defer.zig created+114
...@@ -0,0 +1,114 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const expectError = std.testing.expectError;
5
6var result: [3]u8 = undefined;
7var index: usize = undefined;
8
9fn runSomeErrorDefers(x: bool) !bool {
10 index = 0;
11 defer {
12 result[index] = 'a';
13 index += 1;
14 }
15 errdefer {
16 result[index] = 'b';
17 index += 1;
18 }
19 defer {
20 result[index] = 'c';
21 index += 1;
22 }
23 return if (x) x else error.FalseNotAllowed;
24}
25
26test "mixing normal and error defers" {
27 try expect(runSomeErrorDefers(true) catch unreachable);
28 try expect(result[0] == 'c');
29 try expect(result[1] == 'a');
30
31 const ok = runSomeErrorDefers(false) catch |err| x: {
32 try expect(err == error.FalseNotAllowed);
33 break :x true;
34 };
35 try expect(ok);
36 try expect(result[0] == 'c');
37 try expect(result[1] == 'b');
38 try expect(result[2] == 'a');
39}
40
41test "break and continue inside loop inside defer expression" {
42 testBreakContInDefer(10);
43 comptime testBreakContInDefer(10);
44}
45
46fn testBreakContInDefer(x: usize) void {
47 defer {
48 var i: usize = 0;
49 while (i < x) : (i += 1) {
50 if (i < 5) continue;
51 if (i == 5) break;
52 }
53 expect(i == 5) catch @panic("test failure");
54 }
55}
56
57test "defer and labeled break" {
58 var i = @as(usize, 0);
59
60 blk: {
61 defer i += 1;
62 break :blk;
63 }
64
65 try expect(i == 1);
66}
67
68test "errdefer does not apply to fn inside fn" {
69 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| try expect(e == error.Bad);
70}
71
72fn testNestedFnErrDefer() anyerror!void {
73 var a: i32 = 0;
74 errdefer a += 1;
75 const S = struct {
76 fn baz() anyerror {
77 return error.Bad;
78 }
79 };
80 return S.baz();
81}
82
83test "return variable while defer expression in scope to modify it" {
84 const S = struct {
85 fn doTheTest() !void {
86 try expect(notNull().? == 1);
87 }
88
89 fn notNull() ?u8 {
90 var res: ?u8 = 1;
91 defer res = null;
92 return res;
93 }
94 };
95
96 try S.doTheTest();
97 comptime try S.doTheTest();
98}
99
100test "errdefer with payload" {
101 const S = struct {
102 fn foo() !i32 {
103 errdefer |a| {
104 expectEqual(error.One, a) catch @panic("test failure");
105 }
106 return error.One;
107 }
108 fn doTheTest() !void {
109 try expectError(error.One, foo());
110 }
111 };
112 try S.doTheTest();
113 comptime try S.doTheTest();
114}
test/behavior/enum.zig created+1204
...@@ -0,0 +1,1204 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3const Tag = @import("std").meta.Tag;
4
5test "extern enum" {
6 const S = struct {
7 const i = extern enum {
8 n = 0,
9 o = 2,
10 p = 4,
11 q = 4,
12 };
13 fn doTheTest(y: c_int) void {
14 var x = i.o;
15 switch (x) {
16 .n, .p => unreachable,
17 .o => {},
18 }
19 }
20 };
21 S.doTheTest(52);
22 comptime S.doTheTest(52);
23}
24
25test "non-exhaustive enum" {
26 const S = struct {
27 const E = enum(u8) {
28 a,
29 b,
30 _,
31 };
32 fn doTheTest(y: u8) !void {
33 var e: E = .b;
34 try expect(switch (e) {
35 .a => false,
36 .b => true,
37 _ => false,
38 });
39 e = @intToEnum(E, 12);
40 try expect(switch (e) {
41 .a => false,
42 .b => false,
43 _ => true,
44 });
45
46 try expect(switch (e) {
47 .a => false,
48 .b => false,
49 else => true,
50 });
51 e = .b;
52 try expect(switch (e) {
53 .a => false,
54 else => true,
55 });
56
57 try expect(@typeInfo(E).Enum.fields.len == 2);
58 e = @intToEnum(E, 12);
59 try expect(@enumToInt(e) == 12);
60 e = @intToEnum(E, y);
61 try expect(@enumToInt(e) == 52);
62 try expect(@typeInfo(E).Enum.is_exhaustive == false);
63 }
64 };
65 try S.doTheTest(52);
66 comptime try S.doTheTest(52);
67}
68
69test "empty non-exhaustive enum" {
70 const S = struct {
71 const E = enum(u8) {
72 _,
73 };
74 fn doTheTest(y: u8) !void {
75 var e = @intToEnum(E, y);
76 try expect(switch (e) {
77 _ => true,
78 });
79 try expect(@enumToInt(e) == y);
80
81 try expect(@typeInfo(E).Enum.fields.len == 0);
82 try expect(@typeInfo(E).Enum.is_exhaustive == false);
83 }
84 };
85 try S.doTheTest(42);
86 comptime try S.doTheTest(42);
87}
88
89test "single field non-exhaustive enum" {
90 const S = struct {
91 const E = enum(u8) {
92 a,
93 _,
94 };
95 fn doTheTest(y: u8) !void {
96 var e: E = .a;
97 try expect(switch (e) {
98 .a => true,
99 _ => false,
100 });
101 e = @intToEnum(E, 12);
102 try expect(switch (e) {
103 .a => false,
104 _ => true,
105 });
106
107 try expect(switch (e) {
108 .a => false,
109 else => true,
110 });
111 e = .a;
112 try expect(switch (e) {
113 .a => true,
114 else => false,
115 });
116
117 try expect(@enumToInt(@intToEnum(E, y)) == y);
118 try expect(@typeInfo(E).Enum.fields.len == 1);
119 try expect(@typeInfo(E).Enum.is_exhaustive == false);
120 }
121 };
122 try S.doTheTest(23);
123 comptime try S.doTheTest(23);
124}
125
126test "enum type" {
127 const foo1 = Foo{ .One = 13 };
128 const foo2 = Foo{
129 .Two = Point{
130 .x = 1234,
131 .y = 5678,
132 },
133 };
134 const bar = Bar.B;
135
136 try expect(bar == Bar.B);
137 try expect(@typeInfo(Foo).Union.fields.len == 3);
138 try expect(@typeInfo(Bar).Enum.fields.len == 4);
139 try expect(@sizeOf(Foo) == @sizeOf(FooNoVoid));
140 try expect(@sizeOf(Bar) == 1);
141}
142
143test "enum as return value" {
144 switch (returnAnInt(13)) {
145 Foo.One => |value| try expect(value == 13),
146 else => unreachable,
147 }
148}
149
150const Point = struct {
151 x: u64,
152 y: u64,
153};
154const Foo = union(enum) {
155 One: i32,
156 Two: Point,
157 Three: void,
158};
159const FooNoVoid = union(enum) {
160 One: i32,
161 Two: Point,
162};
163const Bar = enum {
164 A,
165 B,
166 C,
167 D,
168};
169
170fn returnAnInt(x: i32) Foo {
171 return Foo{ .One = x };
172}
173
174test "constant enum with payload" {
175 var empty = AnEnumWithPayload{ .Empty = {} };
176 var full = AnEnumWithPayload{ .Full = 13 };
177 shouldBeEmpty(empty);
178 shouldBeNotEmpty(full);
179}
180
181fn shouldBeEmpty(x: AnEnumWithPayload) void {
182 switch (x) {
183 AnEnumWithPayload.Empty => {},
184 else => unreachable,
185 }
186}
187
188fn shouldBeNotEmpty(x: AnEnumWithPayload) void {
189 switch (x) {
190 AnEnumWithPayload.Empty => unreachable,
191 else => {},
192 }
193}
194
195const AnEnumWithPayload = union(enum) {
196 Empty: void,
197 Full: i32,
198};
199
200const Number = enum {
201 Zero,
202 One,
203 Two,
204 Three,
205 Four,
206};
207
208test "enum to int" {
209 try shouldEqual(Number.Zero, 0);
210 try shouldEqual(Number.One, 1);
211 try shouldEqual(Number.Two, 2);
212 try shouldEqual(Number.Three, 3);
213 try shouldEqual(Number.Four, 4);
214}
215
216fn shouldEqual(n: Number, expected: u3) !void {
217 try expect(@enumToInt(n) == expected);
218}
219
220test "int to enum" {
221 try testIntToEnumEval(3);
222}
223fn testIntToEnumEval(x: i32) !void {
224 try expect(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
225}
226const IntToEnumNumber = enum {
227 Zero,
228 One,
229 Two,
230 Three,
231 Four,
232};
233
234test "@tagName" {
235 try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
236 comptime try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
237}
238
239test "@tagName extern enum with duplicates" {
240 try expect(mem.eql(u8, testEnumTagNameBare(ExternDuplicates.B), "A"));
241 comptime try expect(mem.eql(u8, testEnumTagNameBare(ExternDuplicates.B), "A"));
242}
243
244test "@tagName non-exhaustive enum" {
245 try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
246 comptime try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
247}
248
249fn testEnumTagNameBare(n: anytype) []const u8 {
250 return @tagName(n);
251}
252
253const BareNumber = enum {
254 One,
255 Two,
256 Three,
257};
258
259const ExternDuplicates = extern enum(u8) {
260 A = 1,
261 B = 1,
262};
263
264const NonExhaustive = enum(u8) {
265 A,
266 B,
267 _,
268};
269
270test "enum alignment" {
271 comptime {
272 try expect(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
273 try expect(@alignOf(AlignTestEnum) >= @alignOf(u64));
274 }
275}
276
277const AlignTestEnum = union(enum) {
278 A: [9]u8,
279 B: u64,
280};
281
282const ValueCount1 = enum {
283 I0,
284};
285const ValueCount2 = enum {
286 I0,
287 I1,
288};
289const ValueCount256 = enum {
290 I0,
291 I1,
292 I2,
293 I3,
294 I4,
295 I5,
296 I6,
297 I7,
298 I8,
299 I9,
300 I10,
301 I11,
302 I12,
303 I13,
304 I14,
305 I15,
306 I16,
307 I17,
308 I18,
309 I19,
310 I20,
311 I21,
312 I22,
313 I23,
314 I24,
315 I25,
316 I26,
317 I27,
318 I28,
319 I29,
320 I30,
321 I31,
322 I32,
323 I33,
324 I34,
325 I35,
326 I36,
327 I37,
328 I38,
329 I39,
330 I40,
331 I41,
332 I42,
333 I43,
334 I44,
335 I45,
336 I46,
337 I47,
338 I48,
339 I49,
340 I50,
341 I51,
342 I52,
343 I53,
344 I54,
345 I55,
346 I56,
347 I57,
348 I58,
349 I59,
350 I60,
351 I61,
352 I62,
353 I63,
354 I64,
355 I65,
356 I66,
357 I67,
358 I68,
359 I69,
360 I70,
361 I71,
362 I72,
363 I73,
364 I74,
365 I75,
366 I76,
367 I77,
368 I78,
369 I79,
370 I80,
371 I81,
372 I82,
373 I83,
374 I84,
375 I85,
376 I86,
377 I87,
378 I88,
379 I89,
380 I90,
381 I91,
382 I92,
383 I93,
384 I94,
385 I95,
386 I96,
387 I97,
388 I98,
389 I99,
390 I100,
391 I101,
392 I102,
393 I103,
394 I104,
395 I105,
396 I106,
397 I107,
398 I108,
399 I109,
400 I110,
401 I111,
402 I112,
403 I113,
404 I114,
405 I115,
406 I116,
407 I117,
408 I118,
409 I119,
410 I120,
411 I121,
412 I122,
413 I123,
414 I124,
415 I125,
416 I126,
417 I127,
418 I128,
419 I129,
420 I130,
421 I131,
422 I132,
423 I133,
424 I134,
425 I135,
426 I136,
427 I137,
428 I138,
429 I139,
430 I140,
431 I141,
432 I142,
433 I143,
434 I144,
435 I145,
436 I146,
437 I147,
438 I148,
439 I149,
440 I150,
441 I151,
442 I152,
443 I153,
444 I154,
445 I155,
446 I156,
447 I157,
448 I158,
449 I159,
450 I160,
451 I161,
452 I162,
453 I163,
454 I164,
455 I165,
456 I166,
457 I167,
458 I168,
459 I169,
460 I170,
461 I171,
462 I172,
463 I173,
464 I174,
465 I175,
466 I176,
467 I177,
468 I178,
469 I179,
470 I180,
471 I181,
472 I182,
473 I183,
474 I184,
475 I185,
476 I186,
477 I187,
478 I188,
479 I189,
480 I190,
481 I191,
482 I192,
483 I193,
484 I194,
485 I195,
486 I196,
487 I197,
488 I198,
489 I199,
490 I200,
491 I201,
492 I202,
493 I203,
494 I204,
495 I205,
496 I206,
497 I207,
498 I208,
499 I209,
500 I210,
501 I211,
502 I212,
503 I213,
504 I214,
505 I215,
506 I216,
507 I217,
508 I218,
509 I219,
510 I220,
511 I221,
512 I222,
513 I223,
514 I224,
515 I225,
516 I226,
517 I227,
518 I228,
519 I229,
520 I230,
521 I231,
522 I232,
523 I233,
524 I234,
525 I235,
526 I236,
527 I237,
528 I238,
529 I239,
530 I240,
531 I241,
532 I242,
533 I243,
534 I244,
535 I245,
536 I246,
537 I247,
538 I248,
539 I249,
540 I250,
541 I251,
542 I252,
543 I253,
544 I254,
545 I255,
546};
547const ValueCount257 = enum {
548 I0,
549 I1,
550 I2,
551 I3,
552 I4,
553 I5,
554 I6,
555 I7,
556 I8,
557 I9,
558 I10,
559 I11,
560 I12,
561 I13,
562 I14,
563 I15,
564 I16,
565 I17,
566 I18,
567 I19,
568 I20,
569 I21,
570 I22,
571 I23,
572 I24,
573 I25,
574 I26,
575 I27,
576 I28,
577 I29,
578 I30,
579 I31,
580 I32,
581 I33,
582 I34,
583 I35,
584 I36,
585 I37,
586 I38,
587 I39,
588 I40,
589 I41,
590 I42,
591 I43,
592 I44,
593 I45,
594 I46,
595 I47,
596 I48,
597 I49,
598 I50,
599 I51,
600 I52,
601 I53,
602 I54,
603 I55,
604 I56,
605 I57,
606 I58,
607 I59,
608 I60,
609 I61,
610 I62,
611 I63,
612 I64,
613 I65,
614 I66,
615 I67,
616 I68,
617 I69,
618 I70,
619 I71,
620 I72,
621 I73,
622 I74,
623 I75,
624 I76,
625 I77,
626 I78,
627 I79,
628 I80,
629 I81,
630 I82,
631 I83,
632 I84,
633 I85,
634 I86,
635 I87,
636 I88,
637 I89,
638 I90,
639 I91,
640 I92,
641 I93,
642 I94,
643 I95,
644 I96,
645 I97,
646 I98,
647 I99,
648 I100,
649 I101,
650 I102,
651 I103,
652 I104,
653 I105,
654 I106,
655 I107,
656 I108,
657 I109,
658 I110,
659 I111,
660 I112,
661 I113,
662 I114,
663 I115,
664 I116,
665 I117,
666 I118,
667 I119,
668 I120,
669 I121,
670 I122,
671 I123,
672 I124,
673 I125,
674 I126,
675 I127,
676 I128,
677 I129,
678 I130,
679 I131,
680 I132,
681 I133,
682 I134,
683 I135,
684 I136,
685 I137,
686 I138,
687 I139,
688 I140,
689 I141,
690 I142,
691 I143,
692 I144,
693 I145,
694 I146,
695 I147,
696 I148,
697 I149,
698 I150,
699 I151,
700 I152,
701 I153,
702 I154,
703 I155,
704 I156,
705 I157,
706 I158,
707 I159,
708 I160,
709 I161,
710 I162,
711 I163,
712 I164,
713 I165,
714 I166,
715 I167,
716 I168,
717 I169,
718 I170,
719 I171,
720 I172,
721 I173,
722 I174,
723 I175,
724 I176,
725 I177,
726 I178,
727 I179,
728 I180,
729 I181,
730 I182,
731 I183,
732 I184,
733 I185,
734 I186,
735 I187,
736 I188,
737 I189,
738 I190,
739 I191,
740 I192,
741 I193,
742 I194,
743 I195,
744 I196,
745 I197,
746 I198,
747 I199,
748 I200,
749 I201,
750 I202,
751 I203,
752 I204,
753 I205,
754 I206,
755 I207,
756 I208,
757 I209,
758 I210,
759 I211,
760 I212,
761 I213,
762 I214,
763 I215,
764 I216,
765 I217,
766 I218,
767 I219,
768 I220,
769 I221,
770 I222,
771 I223,
772 I224,
773 I225,
774 I226,
775 I227,
776 I228,
777 I229,
778 I230,
779 I231,
780 I232,
781 I233,
782 I234,
783 I235,
784 I236,
785 I237,
786 I238,
787 I239,
788 I240,
789 I241,
790 I242,
791 I243,
792 I244,
793 I245,
794 I246,
795 I247,
796 I248,
797 I249,
798 I250,
799 I251,
800 I252,
801 I253,
802 I254,
803 I255,
804 I256,
805};
806
807test "enum sizes" {
808 comptime {
809 try expect(@sizeOf(ValueCount1) == 0);
810 try expect(@sizeOf(ValueCount2) == 1);
811 try expect(@sizeOf(ValueCount256) == 1);
812 try expect(@sizeOf(ValueCount257) == 2);
813 }
814}
815
816const Small2 = enum(u2) {
817 One,
818 Two,
819};
820const Small = enum(u2) {
821 One,
822 Two,
823 Three,
824 Four,
825};
826
827test "set enum tag type" {
828 {
829 var x = Small.One;
830 x = Small.Two;
831 comptime try expect(Tag(Small) == u2);
832 }
833 {
834 var x = Small2.One;
835 x = Small2.Two;
836 comptime try expect(Tag(Small2) == u2);
837 }
838}
839
840const A = enum(u3) {
841 One,
842 Two,
843 Three,
844 Four,
845 One2,
846 Two2,
847 Three2,
848 Four2,
849};
850
851const B = enum(u3) {
852 One3,
853 Two3,
854 Three3,
855 Four3,
856 One23,
857 Two23,
858 Three23,
859 Four23,
860};
861
862const C = enum(u2) {
863 One4,
864 Two4,
865 Three4,
866 Four4,
867};
868
869const BitFieldOfEnums = packed struct {
870 a: A,
871 b: B,
872 c: C,
873};
874
875const bit_field_1 = BitFieldOfEnums{
876 .a = A.Two,
877 .b = B.Three3,
878 .c = C.Four4,
879};
880
881test "bit field access with enum fields" {
882 var data = bit_field_1;
883 try expect(getA(&data) == A.Two);
884 try expect(getB(&data) == B.Three3);
885 try expect(getC(&data) == C.Four4);
886 comptime try expect(@sizeOf(BitFieldOfEnums) == 1);
887
888 data.b = B.Four3;
889 try expect(data.b == B.Four3);
890
891 data.a = A.Three;
892 try expect(data.a == A.Three);
893 try expect(data.b == B.Four3);
894}
895
896fn getA(data: *const BitFieldOfEnums) A {
897 return data.a;
898}
899
900fn getB(data: *const BitFieldOfEnums) B {
901 return data.b;
902}
903
904fn getC(data: *const BitFieldOfEnums) C {
905 return data.c;
906}
907
908test "casting enum to its tag type" {
909 try testCastEnumTag(Small2.Two);
910 comptime try testCastEnumTag(Small2.Two);
911}
912
913fn testCastEnumTag(value: Small2) !void {
914 try expect(@enumToInt(value) == 1);
915}
916
917const MultipleChoice = enum(u32) {
918 A = 20,
919 B = 40,
920 C = 60,
921 D = 1000,
922};
923
924test "enum with specified tag values" {
925 try testEnumWithSpecifiedTagValues(MultipleChoice.C);
926 comptime try testEnumWithSpecifiedTagValues(MultipleChoice.C);
927}
928
929fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {
930 try expect(@enumToInt(x) == 60);
931 try expect(1234 == switch (x) {
932 MultipleChoice.A => 1,
933 MultipleChoice.B => 2,
934 MultipleChoice.C => @as(u32, 1234),
935 MultipleChoice.D => 4,
936 });
937}
938
939const MultipleChoice2 = enum(u32) {
940 Unspecified1,
941 A = 20,
942 Unspecified2,
943 B = 40,
944 Unspecified3,
945 C = 60,
946 Unspecified4,
947 D = 1000,
948 Unspecified5,
949};
950
951test "enum with specified and unspecified tag values" {
952 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
953 comptime try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
954}
955
956fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void {
957 try expect(@enumToInt(x) == 1000);
958 try expect(1234 == switch (x) {
959 MultipleChoice2.A => 1,
960 MultipleChoice2.B => 2,
961 MultipleChoice2.C => 3,
962 MultipleChoice2.D => @as(u32, 1234),
963 MultipleChoice2.Unspecified1 => 5,
964 MultipleChoice2.Unspecified2 => 6,
965 MultipleChoice2.Unspecified3 => 7,
966 MultipleChoice2.Unspecified4 => 8,
967 MultipleChoice2.Unspecified5 => 9,
968 });
969}
970
971test "cast integer literal to enum" {
972 try expect(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
973 try expect(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
974}
975
976const EnumWithOneMember = enum {
977 Eof,
978};
979
980fn doALoopThing(id: EnumWithOneMember) void {
981 while (true) {
982 if (id == EnumWithOneMember.Eof) {
983 break;
984 }
985 @compileError("above if condition should be comptime");
986 }
987}
988
989test "comparison operator on enum with one member is comptime known" {
990 doALoopThing(EnumWithOneMember.Eof);
991}
992
993const State = enum {
994 Start,
995};
996test "switch on enum with one member is comptime known" {
997 var state = State.Start;
998 switch (state) {
999 State.Start => return,
1000 }
1001 @compileError("analysis should not reach here");
1002}
1003
1004const EnumWithTagValues = enum(u4) {
1005 A = 1 << 0,
1006 B = 1 << 1,
1007 C = 1 << 2,
1008 D = 1 << 3,
1009};
1010test "enum with tag values don't require parens" {
1011 try expect(@enumToInt(EnumWithTagValues.C) == 0b0100);
1012}
1013
1014test "enum with 1 field but explicit tag type should still have the tag type" {
1015 const Enum = enum(u8) {
1016 B = 2,
1017 };
1018 comptime try expect(@sizeOf(Enum) == @sizeOf(u8));
1019}
1020
1021test "empty extern enum with members" {
1022 const E = extern enum {
1023 A,
1024 B,
1025 C,
1026 };
1027 try expect(@sizeOf(E) == @sizeOf(c_int));
1028}
1029
1030test "tag name with assigned enum values" {
1031 const LocalFoo = enum {
1032 A = 1,
1033 B = 0,
1034 };
1035 var b = LocalFoo.B;
1036 try expect(mem.eql(u8, @tagName(b), "B"));
1037}
1038
1039test "enum literal equality" {
1040 const x = .hi;
1041 const y = .ok;
1042 const z = .hi;
1043
1044 try expect(x != y);
1045 try expect(x == z);
1046}
1047
1048test "enum literal cast to enum" {
1049 const Color = enum {
1050 Auto,
1051 Off,
1052 On,
1053 };
1054
1055 var color1: Color = .Auto;
1056 var color2 = Color.Auto;
1057 try expect(color1 == color2);
1058}
1059
1060test "peer type resolution with enum literal" {
1061 const Items = enum {
1062 one,
1063 two,
1064 };
1065
1066 try expect(Items.two == .two);
1067 try expect(.two == Items.two);
1068}
1069
1070test "enum literal in array literal" {
1071 const Items = enum {
1072 one,
1073 two,
1074 };
1075
1076 const array = [_]Items{
1077 .one,
1078 .two,
1079 };
1080
1081 try expect(array[0] == .one);
1082 try expect(array[1] == .two);
1083}
1084
1085test "signed integer as enum tag" {
1086 const SignedEnum = enum(i2) {
1087 A0 = -1,
1088 A1 = 0,
1089 A2 = 1,
1090 };
1091
1092 try expect(@enumToInt(SignedEnum.A0) == -1);
1093 try expect(@enumToInt(SignedEnum.A1) == 0);
1094 try expect(@enumToInt(SignedEnum.A2) == 1);
1095}
1096
1097test "enum value allocation" {
1098 const LargeEnum = enum(u32) {
1099 A0 = 0x80000000,
1100 A1,
1101 A2,
1102 };
1103
1104 try expect(@enumToInt(LargeEnum.A0) == 0x80000000);
1105 try expect(@enumToInt(LargeEnum.A1) == 0x80000001);
1106 try expect(@enumToInt(LargeEnum.A2) == 0x80000002);
1107}
1108
1109test "enum literal casting to tagged union" {
1110 const Arch = union(enum) {
1111 x86_64,
1112 arm: Arm32,
1113
1114 const Arm32 = enum {
1115 v8_5a,
1116 v8_4a,
1117 };
1118 };
1119
1120 var t = true;
1121 var x: Arch = .x86_64;
1122 var y = if (t) x else .x86_64;
1123 switch (y) {
1124 .x86_64 => {},
1125 else => @panic("fail"),
1126 }
1127}
1128
1129test "enum with one member and custom tag type" {
1130 const E = enum(u2) {
1131 One,
1132 };
1133 try expect(@enumToInt(E.One) == 0);
1134 const E2 = enum(u2) {
1135 One = 2,
1136 };
1137 try expect(@enumToInt(E2.One) == 2);
1138}
1139
1140test "enum literal casting to optional" {
1141 var bar: ?Bar = undefined;
1142 bar = .B;
1143
1144 try expect(bar.? == Bar.B);
1145}
1146
1147test "enum literal casting to error union with payload enum" {
1148 var bar: error{B}!Bar = undefined;
1149 bar = .B; // should never cast to the error set
1150
1151 try expect((try bar) == Bar.B);
1152}
1153
1154test "enum with one member and u1 tag type @enumToInt" {
1155 const Enum = enum(u1) {
1156 Test,
1157 };
1158 try expect(@enumToInt(Enum.Test) == 0);
1159}
1160
1161test "enum with comptime_int tag type" {
1162 const Enum = enum(comptime_int) {
1163 One = 3,
1164 Two = 2,
1165 Three = 1,
1166 };
1167 comptime try expect(Tag(Enum) == comptime_int);
1168}
1169
1170test "enum with one member default to u0 tag type" {
1171 const E0 = enum {
1172 X,
1173 };
1174 comptime try expect(Tag(E0) == u0);
1175}
1176
1177test "tagName on enum literals" {
1178 try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
1179 comptime try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
1180}
1181
1182test "method call on an enum" {
1183 const S = struct {
1184 const E = enum {
1185 one,
1186 two,
1187
1188 fn method(self: *E) bool {
1189 return self.* == .two;
1190 }
1191
1192 fn generic_method(self: *E, foo: anytype) bool {
1193 return self.* == .two and foo == bool;
1194 }
1195 };
1196 fn doTheTest() !void {
1197 var e = E.two;
1198 try expect(e.method());
1199 try expect(e.generic_method(bool));
1200 }
1201 };
1202 try S.doTheTest();
1203 comptime try S.doTheTest();
1204}
test/behavior/enum_with_members.zig created+27
...@@ -0,0 +1,27 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3const fmt = @import("std").fmt;
4
5const ET = union(enum) {
6 SINT: i32,
7 UINT: u32,
8
9 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
10 return switch (a.*) {
11 ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}),
12 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}),
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 try expect((a.print(buf[0..]) catch unreachable) == 3);
23 try expect(mem.eql(u8, buf[0..3], "-42"));
24
25 try expect((b.print(buf[0..]) catch unreachable) == 2);
26 try expect(mem.eql(u8, buf[0..2], "42"));
27}
test/behavior/error.zig created+452
...@@ -0,0 +1,452 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectError = std.testing.expectError;
4const expectEqual = std.testing.expectEqual;
5const mem = std.mem;
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 try expect((baz() catch unreachable) == 15);
23}
24
25fn gimmeItBroke() []const u8 {
26 return @errorName(error.ItBroke);
27}
28
29test "@errorName" {
30 try expect(mem.eql(u8, @errorName(error.AnError), "AnError"));
31 try expect(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
32}
33
34test "error values" {
35 const a = @errorToInt(error.err1);
36 const b = @errorToInt(error.err2);
37 try expect(a != b);
38}
39
40test "redefinition of error values allowed" {
41 shouldBeNotEqual(error.AnError, error.SecondError);
42}
43fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
44 if (a == b) unreachable;
45}
46
47test "error binary operator" {
48 const a = errBinaryOperatorG(true) catch 3;
49 const b = errBinaryOperatorG(false) catch 3;
50 try expect(a == 3);
51 try expect(b == 10);
52}
53fn errBinaryOperatorG(x: bool) anyerror!isize {
54 return if (x) error.ItBroke else @as(isize, 10);
55}
56
57test "unwrap simple value from error" {
58 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
59 try expect(i == 13);
60}
61fn unwrapSimpleValueFromErrorDo() anyerror!isize {
62 return 13;
63}
64
65test "error return in assignment" {
66 doErrReturnInAssignment() catch unreachable;
67}
68
69fn doErrReturnInAssignment() anyerror!void {
70 var x: i32 = undefined;
71 x = try makeANonErr();
72}
73
74fn makeANonErr() anyerror!i32 {
75 return 1;
76}
77
78test "error union type " {
79 try testErrorUnionType();
80 comptime try testErrorUnionType();
81}
82
83fn testErrorUnionType() !void {
84 const x: anyerror!i32 = 1234;
85 if (x) |value| try expect(value == 1234) else |_| unreachable;
86 try expect(@typeInfo(@TypeOf(x)) == .ErrorUnion);
87 try expect(@typeInfo(@typeInfo(@TypeOf(x)).ErrorUnion.error_set) == .ErrorSet);
88 try expect(@typeInfo(@TypeOf(x)).ErrorUnion.error_set == anyerror);
89}
90
91test "error set type" {
92 try testErrorSetType();
93 comptime try testErrorSetType();
94}
95
96const MyErrSet = error{
97 OutOfMemory,
98 FileNotFound,
99};
100
101fn testErrorSetType() !void {
102 try expect(@typeInfo(MyErrSet).ErrorSet.?.len == 2);
103
104 const a: MyErrSet!i32 = 5678;
105 const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
106
107 if (a) |value| try expect(value == 5678) else |err| switch (err) {
108 error.OutOfMemory => unreachable,
109 error.FileNotFound => unreachable,
110 }
111}
112
113test "explicit error set cast" {
114 try testExplicitErrorSetCast(Set1.A);
115 comptime try 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 try expect(y == error.A);
131}
132
133test "comptime test error for empty error set" {
134 try testComptimeTestErrorEmptySet(1234);
135 comptime try testComptimeTestErrorEmptySet(1234);
136}
137
138const EmptyErrorSet = error{};
139
140fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) !void {
141 if (x) |v| try expect(v == 1234) else |err| @compileError("bad");
142}
143
144test "syntax: optional operator in front of error union operator" {
145 comptime {
146 try expect(?(anyerror!i32) == ?(anyerror!i32));
147 }
148}
149
150test "comptime err to int of error set with only 1 possible value" {
151 testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
152 comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
153}
154fn testErrToIntWithOnePossibleValue(
155 x: error{A},
156 comptime value: u32,
157) void {
158 if (@errorToInt(x) != value) {
159 @compileError("bad");
160 }
161}
162
163test "empty error union" {
164 const x = error{} || error{};
165}
166
167test "error union peer type resolution" {
168 try testErrorUnionPeerTypeResolution(1);
169}
170
171fn testErrorUnionPeerTypeResolution(x: i32) !void {
172 const y = switch (x) {
173 1 => bar_1(),
174 2 => baz_1(),
175 else => quux_1(),
176 };
177 if (y) |_| {
178 @panic("expected error");
179 } else |e| {
180 try expect(e == error.A);
181 }
182}
183
184fn bar_1() anyerror {
185 return error.A;
186}
187
188fn baz_1() !i32 {
189 return error.B;
190}
191
192fn quux_1() !i32 {
193 return error.C;
194}
195
196test "error: fn returning empty error set can be passed as fn returning any error" {
197 entry();
198 comptime entry();
199}
200
201fn entry() void {
202 foo2(bar2);
203}
204
205fn foo2(f: fn () anyerror!void) void {
206 const x = f();
207}
208
209fn bar2() (error{}!void) {}
210
211test "error: Zero sized error set returned with value payload crash" {
212 _ = foo3(0) catch {};
213 _ = comptime foo3(0) catch {};
214}
215
216const Error = error{};
217fn foo3(b: usize) Error!usize {
218 return b;
219}
220
221test "error: Infer error set from literals" {
222 _ = nullLiteral("n") catch |err| handleErrors(err);
223 _ = floatLiteral("n") catch |err| handleErrors(err);
224 _ = intLiteral("n") catch |err| handleErrors(err);
225 _ = comptime nullLiteral("n") catch |err| handleErrors(err);
226 _ = comptime floatLiteral("n") catch |err| handleErrors(err);
227 _ = comptime intLiteral("n") catch |err| handleErrors(err);
228}
229
230fn handleErrors(err: anytype) noreturn {
231 switch (err) {
232 error.T => {},
233 }
234
235 unreachable;
236}
237
238fn nullLiteral(str: []const u8) !?i64 {
239 if (str[0] == 'n') return null;
240
241 return error.T;
242}
243
244fn floatLiteral(str: []const u8) !?f64 {
245 if (str[0] == 'n') return 1.0;
246
247 return error.T;
248}
249
250fn intLiteral(str: []const u8) !?i64 {
251 if (str[0] == 'n') return 1;
252
253 return error.T;
254}
255
256test "nested error union function call in optional unwrap" {
257 const S = struct {
258 const Foo = struct {
259 a: i32,
260 };
261
262 fn errorable() !i32 {
263 var x: Foo = (try getFoo()) orelse return error.Other;
264 return x.a;
265 }
266
267 fn errorable2() !i32 {
268 var x: Foo = (try getFoo2()) orelse return error.Other;
269 return x.a;
270 }
271
272 fn errorable3() !i32 {
273 var x: Foo = (try getFoo3()) orelse return error.Other;
274 return x.a;
275 }
276
277 fn getFoo() anyerror!?Foo {
278 return Foo{ .a = 1234 };
279 }
280
281 fn getFoo2() anyerror!?Foo {
282 return error.Failure;
283 }
284
285 fn getFoo3() anyerror!?Foo {
286 return null;
287 }
288 };
289 try expect((try S.errorable()) == 1234);
290 try expectError(error.Failure, S.errorable2());
291 try expectError(error.Other, S.errorable3());
292 comptime {
293 try expect((try S.errorable()) == 1234);
294 try expectError(error.Failure, S.errorable2());
295 try expectError(error.Other, S.errorable3());
296 }
297}
298
299test "widen cast integer payload of error union function call" {
300 const S = struct {
301 fn errorable() !u64 {
302 var x = @as(u64, try number());
303 return x;
304 }
305
306 fn number() anyerror!u32 {
307 return 1234;
308 }
309 };
310 try expect((try S.errorable()) == 1234);
311}
312
313test "return function call to error set from error union function" {
314 const S = struct {
315 fn errorable() anyerror!i32 {
316 return fail();
317 }
318
319 fn fail() anyerror {
320 return error.Failure;
321 }
322 };
323 try expectError(error.Failure, S.errorable());
324 comptime try expectError(error.Failure, S.errorable());
325}
326
327test "optional error set is the same size as error set" {
328 comptime try expect(@sizeOf(?anyerror) == @sizeOf(anyerror));
329 const S = struct {
330 fn returnsOptErrSet() ?anyerror {
331 return null;
332 }
333 };
334 try expect(S.returnsOptErrSet() == null);
335 comptime try expect(S.returnsOptErrSet() == null);
336}
337
338test "debug info for optional error set" {
339 const SomeError = error{Hello};
340 var a_local_variable: ?SomeError = null;
341}
342
343test "nested catch" {
344 const S = struct {
345 fn entry() !void {
346 try expectError(error.Bad, func());
347 }
348 fn fail() anyerror!Foo {
349 return error.Wrong;
350 }
351 fn func() anyerror!Foo {
352 const x = fail() catch
353 fail() catch
354 return error.Bad;
355 unreachable;
356 }
357 const Foo = struct {
358 field: i32,
359 };
360 };
361 try S.entry();
362 comptime try S.entry();
363}
364
365test "implicit cast to optional to error union to return result loc" {
366 const S = struct {
367 fn entry() !void {
368 var x: Foo = undefined;
369 if (func(&x)) |opt| {
370 try expect(opt != null);
371 } else |_| @panic("expected non error");
372 }
373 fn func(f: *Foo) anyerror!?*Foo {
374 return f;
375 }
376 const Foo = struct {
377 field: i32,
378 };
379 };
380 try S.entry();
381 //comptime S.entry(); TODO
382}
383
384test "function pointer with return type that is error union with payload which is pointer of parent struct" {
385 const S = struct {
386 const Foo = struct {
387 fun: fn (a: i32) (anyerror!*Foo),
388 };
389
390 const Err = error{UnspecifiedErr};
391
392 fn bar(a: i32) anyerror!*Foo {
393 return Err.UnspecifiedErr;
394 }
395
396 fn doTheTest() !void {
397 var x = Foo{ .fun = bar };
398 try expectError(error.UnspecifiedErr, x.fun(1));
399 }
400 };
401 try S.doTheTest();
402}
403
404test "return result loc as peer result loc in inferred error set function" {
405 const S = struct {
406 fn doTheTest() !void {
407 if (foo(2)) |x| {
408 try expect(x.Two);
409 } else |e| switch (e) {
410 error.Whatever => @panic("fail"),
411 }
412 try expectError(error.Whatever, foo(99));
413 }
414 const FormValue = union(enum) {
415 One: void,
416 Two: bool,
417 };
418
419 fn foo(id: u64) !FormValue {
420 return switch (id) {
421 2 => FormValue{ .Two = true },
422 1 => FormValue{ .One = {} },
423 else => return error.Whatever,
424 };
425 }
426 };
427 try S.doTheTest();
428 comptime try S.doTheTest();
429}
430
431test "error payload type is correctly resolved" {
432 const MyIntWrapper = struct {
433 const Self = @This();
434
435 x: i32,
436
437 pub fn create() anyerror!Self {
438 return Self{ .x = 42 };
439 }
440 };
441
442 try expectEqual(MyIntWrapper{ .x = 42 }, try MyIntWrapper.create());
443}
444
445test "error union comptime caching" {
446 const S = struct {
447 fn foo(comptime arg: anytype) void {}
448 };
449
450 S.foo(@as(anyerror!void, {}));
451 S.foo(@as(anyerror!void, {}));
452}
test/behavior/eval.zig created+832
...@@ -0,0 +1,832 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4
5test "compile time recursion" {
6 try expect(some_data.len == 21);
7}
8var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined;
9fn fibonacci(x: i32) i32 {
10 if (x <= 1) return 1;
11 return fibonacci(x - 1) + fibonacci(x - 2);
12}
13
14fn unwrapAndAddOne(blah: ?i32) i32 {
15 return blah.? + 1;
16}
17const should_be_1235 = unwrapAndAddOne(1234);
18test "static add one" {
19 try expect(should_be_1235 == 1235);
20}
21
22test "inlined loop" {
23 comptime var i = 0;
24 comptime var sum = 0;
25 inline while (i <= 5) : (i += 1)
26 sum += i;
27 try expect(sum == 15);
28}
29
30fn gimme1or2(comptime a: bool) i32 {
31 const x: i32 = 1;
32 const y: i32 = 2;
33 comptime var z: i32 = if (a) x else y;
34 return z;
35}
36test "inline variable gets result of const if" {
37 try expect(gimme1or2(true) == 1);
38 try expect(gimme1or2(false) == 2);
39}
40
41test "static function evaluation" {
42 try expect(statically_added_number == 3);
43}
44const statically_added_number = staticAdd(1, 2);
45fn staticAdd(a: i32, b: i32) i32 {
46 return a + b;
47}
48
49test "const expr eval on single expr blocks" {
50 try expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
51 comptime try expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
52}
53
54fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
55 const literal = 3;
56
57 const result = if (b) b: {
58 break :b literal;
59 } else b: {
60 break :b x;
61 };
62
63 return result;
64}
65
66test "statically initialized list" {
67 try expect(static_point_list[0].x == 1);
68 try expect(static_point_list[0].y == 2);
69 try expect(static_point_list[1].x == 3);
70 try expect(static_point_list[1].y == 4);
71}
72const Point = struct {
73 x: i32,
74 y: i32,
75};
76const static_point_list = [_]Point{
77 makePoint(1, 2),
78 makePoint(3, 4),
79};
80fn makePoint(x: i32, y: i32) Point {
81 return Point{
82 .x = x,
83 .y = y,
84 };
85}
86
87test "static eval list init" {
88 try expect(static_vec3.data[2] == 1.0);
89 try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
90}
91const static_vec3 = vec3(0.0, 0.0, 1.0);
92pub const Vec3 = struct {
93 data: [3]f32,
94};
95pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
96 return Vec3{
97 .data = [_]f32{
98 x,
99 y,
100 z,
101 },
102 };
103}
104
105test "constant expressions" {
106 var array: [array_size]u8 = undefined;
107 try expect(@sizeOf(@TypeOf(array)) == 20);
108}
109const array_size: u8 = 20;
110
111test "constant struct with negation" {
112 try expect(vertices[0].x == -0.6);
113}
114const Vertex = struct {
115 x: f32,
116 y: f32,
117 r: f32,
118 g: f32,
119 b: f32,
120};
121const vertices = [_]Vertex{
122 Vertex{
123 .x = -0.6,
124 .y = -0.4,
125 .r = 1.0,
126 .g = 0.0,
127 .b = 0.0,
128 },
129 Vertex{
130 .x = 0.6,
131 .y = -0.4,
132 .r = 0.0,
133 .g = 1.0,
134 .b = 0.0,
135 },
136 Vertex{
137 .x = 0.0,
138 .y = 0.6,
139 .r = 0.0,
140 .g = 0.0,
141 .b = 1.0,
142 },
143};
144
145test "statically initialized struct" {
146 st_init_str_foo.x += 1;
147 try expect(st_init_str_foo.x == 14);
148}
149const StInitStrFoo = struct {
150 x: i32,
151 y: bool,
152};
153var st_init_str_foo = StInitStrFoo{
154 .x = 13,
155 .y = true,
156};
157
158test "statically initalized array literal" {
159 const y: [4]u8 = st_init_arr_lit_x;
160 try expect(y[3] == 4);
161}
162const st_init_arr_lit_x = [_]u8{
163 1,
164 2,
165 3,
166 4,
167};
168
169test "const slice" {
170 comptime {
171 const a = "1234567890";
172 try expect(a.len == 10);
173 const b = a[1..2];
174 try expect(b.len == 1);
175 try expect(b[0] == '2');
176 }
177}
178
179test "try to trick eval with runtime if" {
180 try expect(testTryToTrickEvalWithRuntimeIf(true) == 10);
181}
182
183fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
184 comptime var i: usize = 0;
185 inline while (i < 10) : (i += 1) {
186 const result = if (b) false else true;
187 }
188 comptime {
189 return i;
190 }
191}
192
193test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
194 var runtime = [1]i32{3};
195 comptime var i: usize = 0;
196 inline while (i < 2) : (i += 1) {
197 const result = if (i == 0) [1]i32{2} else runtime;
198 }
199 comptime {
200 try expect(i == 2);
201 }
202}
203
204fn max(comptime T: type, a: T, b: T) T {
205 if (T == bool) {
206 return a or b;
207 } else if (a > b) {
208 return a;
209 } else {
210 return b;
211 }
212}
213fn letsTryToCompareBools(a: bool, b: bool) bool {
214 return max(bool, a, b);
215}
216test "inlined block and runtime block phi" {
217 try expect(letsTryToCompareBools(true, true));
218 try expect(letsTryToCompareBools(true, false));
219 try expect(letsTryToCompareBools(false, true));
220 try expect(!letsTryToCompareBools(false, false));
221
222 comptime {
223 try expect(letsTryToCompareBools(true, true));
224 try expect(letsTryToCompareBools(true, false));
225 try expect(letsTryToCompareBools(false, true));
226 try expect(!letsTryToCompareBools(false, false));
227 }
228}
229
230const CmdFn = struct {
231 name: []const u8,
232 func: fn (i32) i32,
233};
234
235const cmd_fns = [_]CmdFn{
236 CmdFn{
237 .name = "one",
238 .func = one,
239 },
240 CmdFn{
241 .name = "two",
242 .func = two,
243 },
244 CmdFn{
245 .name = "three",
246 .func = three,
247 },
248};
249fn one(value: i32) i32 {
250 return value + 1;
251}
252fn two(value: i32) i32 {
253 return value + 2;
254}
255fn three(value: i32) i32 {
256 return value + 3;
257}
258
259fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
260 var result: i32 = start_value;
261 comptime var i = 0;
262 inline while (i < cmd_fns.len) : (i += 1) {
263 if (cmd_fns[i].name[0] == prefix_char) {
264 result = cmd_fns[i].func(result);
265 }
266 }
267 return result;
268}
269
270test "comptime iterate over fn ptr list" {
271 try expect(performFn('t', 1) == 6);
272 try expect(performFn('o', 0) == 1);
273 try expect(performFn('w', 99) == 99);
274}
275
276test "eval @setRuntimeSafety at compile-time" {
277 const result = comptime fnWithSetRuntimeSafety();
278 try expect(result == 1234);
279}
280
281fn fnWithSetRuntimeSafety() i32 {
282 @setRuntimeSafety(true);
283 return 1234;
284}
285
286test "eval @setFloatMode at compile-time" {
287 const result = comptime fnWithFloatMode();
288 try expect(result == 1234.0);
289}
290
291fn fnWithFloatMode() f32 {
292 @setFloatMode(std.builtin.FloatMode.Strict);
293 return 1234.0;
294}
295
296const SimpleStruct = struct {
297 field: i32,
298
299 fn method(self: *const SimpleStruct) i32 {
300 return self.field + 3;
301 }
302};
303
304var simple_struct = SimpleStruct{ .field = 1234 };
305
306const bound_fn = simple_struct.method;
307
308test "call method on bound fn referring to var instance" {
309 try expect(bound_fn() == 1237);
310}
311
312test "ptr to local array argument at comptime" {
313 comptime {
314 var bytes: [10]u8 = undefined;
315 modifySomeBytes(bytes[0..]);
316 try expect(bytes[0] == 'a');
317 try expect(bytes[9] == 'b');
318 }
319}
320
321fn modifySomeBytes(bytes: []u8) void {
322 bytes[0] = 'a';
323 bytes[9] = 'b';
324}
325
326test "comparisons 0 <= uint and 0 > uint should be comptime" {
327 testCompTimeUIntComparisons(1234);
328}
329fn testCompTimeUIntComparisons(x: u32) void {
330 if (!(0 <= x)) {
331 @compileError("this condition should be comptime known");
332 }
333 if (0 > x) {
334 @compileError("this condition should be comptime known");
335 }
336 if (!(x >= 0)) {
337 @compileError("this condition should be comptime known");
338 }
339 if (x < 0) {
340 @compileError("this condition should be comptime known");
341 }
342}
343
344test "const ptr to variable data changes at runtime" {
345 try expect(foo_ref.name[0] == 'a');
346 foo_ref.name = "b";
347 try expect(foo_ref.name[0] == 'b');
348}
349
350const Foo = struct {
351 name: []const u8,
352};
353
354var foo_contents = Foo{ .name = "a" };
355const foo_ref = &foo_contents;
356
357test "create global array with for loop" {
358 try expect(global_array[5] == 5 * 5);
359 try expect(global_array[9] == 9 * 9);
360}
361
362const global_array = x: {
363 var result: [10]usize = undefined;
364 for (result) |*item, index| {
365 item.* = index * index;
366 }
367 break :x result;
368};
369
370test "compile-time downcast when the bits fit" {
371 comptime {
372 const spartan_count: u16 = 255;
373 const byte = @intCast(u8, spartan_count);
374 try expect(byte == 255);
375 }
376}
377
378const hi1 = "hi";
379const hi2 = hi1;
380test "const global shares pointer with other same one" {
381 try assertEqualPtrs(&hi1[0], &hi2[0]);
382 comptime try expect(&hi1[0] == &hi2[0]);
383}
384fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void {
385 try expect(ptr1 == ptr2);
386}
387
388test "@setEvalBranchQuota" {
389 comptime {
390 // 1001 for the loop and then 1 more for the expect fn call
391 @setEvalBranchQuota(1002);
392 var i = 0;
393 var sum = 0;
394 while (i < 1001) : (i += 1) {
395 sum += i;
396 }
397 try expect(sum == 500500);
398 }
399}
400
401test "float literal at compile time not lossy" {
402 try expect(16777216.0 + 1.0 == 16777217.0);
403 try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
404}
405
406test "f32 at compile time is lossy" {
407 try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
408}
409
410test "f64 at compile time is lossy" {
411 try expect(@as(f64, 1 << 53) + 1 == 1 << 53);
412}
413
414test "f128 at compile time is lossy" {
415 try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
416}
417
418comptime {
419 try expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192);
420}
421
422pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
423 return struct {
424 pub const Node = struct {};
425 };
426}
427
428test "string literal used as comptime slice is memoized" {
429 const a = "link";
430 const b = "link";
431 comptime try expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
432 comptime try expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
433}
434
435test "comptime slice of undefined pointer of length 0" {
436 const slice1 = @as([*]i32, undefined)[0..0];
437 try expect(slice1.len == 0);
438 const slice2 = @as([*]i32, undefined)[100..100];
439 try expect(slice2.len == 0);
440}
441
442fn copyWithPartialInline(s: []u32, b: []u8) void {
443 comptime var i: usize = 0;
444 inline while (i < 4) : (i += 1) {
445 s[i] = 0;
446 s[i] |= @as(u32, b[i * 4 + 0]) << 24;
447 s[i] |= @as(u32, b[i * 4 + 1]) << 16;
448 s[i] |= @as(u32, b[i * 4 + 2]) << 8;
449 s[i] |= @as(u32, b[i * 4 + 3]) << 0;
450 }
451}
452
453test "binary math operator in partially inlined function" {
454 var s: [4]u32 = undefined;
455 var b: [16]u8 = undefined;
456
457 for (b) |*r, i|
458 r.* = @intCast(u8, i + 1);
459
460 copyWithPartialInline(s[0..], b[0..]);
461 try expect(s[0] == 0x1020304);
462 try expect(s[1] == 0x5060708);
463 try expect(s[2] == 0x90a0b0c);
464 try expect(s[3] == 0xd0e0f10);
465}
466
467test "comptime function with the same args is memoized" {
468 comptime {
469 try expect(MakeType(i32) == MakeType(i32));
470 try expect(MakeType(i32) != MakeType(f64));
471 }
472}
473
474fn MakeType(comptime T: type) type {
475 return struct {
476 field: T,
477 };
478}
479
480test "comptime function with mutable pointer is not memoized" {
481 comptime {
482 var x: i32 = 1;
483 const ptr = &x;
484 increment(ptr);
485 increment(ptr);
486 try expect(x == 3);
487 }
488}
489
490fn increment(value: *i32) void {
491 value.* += 1;
492}
493
494fn generateTable(comptime T: type) [1010]T {
495 var res: [1010]T = undefined;
496 var i: usize = 0;
497 while (i < 1010) : (i += 1) {
498 res[i] = @intCast(T, i);
499 }
500 return res;
501}
502
503fn doesAlotT(comptime T: type, value: usize) T {
504 @setEvalBranchQuota(5000);
505 const table = comptime blk: {
506 break :blk generateTable(T);
507 };
508 return table[value];
509}
510
511test "@setEvalBranchQuota at same scope as generic function call" {
512 try expect(doesAlotT(u32, 2) == 2);
513}
514
515test "comptime slice of slice preserves comptime var" {
516 comptime {
517 var buff: [10]u8 = undefined;
518 buff[0..][0..][0] = 1;
519 try expect(buff[0..][0..][0] == 1);
520 }
521}
522
523test "comptime slice of pointer preserves comptime var" {
524 comptime {
525 var buff: [10]u8 = undefined;
526 var a = @ptrCast([*]u8, &buff);
527 a[0..1][0] = 1;
528 try expect(buff[0..][0..][0] == 1);
529 }
530}
531
532const SingleFieldStruct = struct {
533 x: i32,
534
535 fn read_x(self: *const SingleFieldStruct) i32 {
536 return self.x;
537 }
538};
539test "const ptr to comptime mutable data is not memoized" {
540 comptime {
541 var foo = SingleFieldStruct{ .x = 1 };
542 try expect(foo.read_x() == 1);
543 foo.x = 2;
544 try expect(foo.read_x() == 2);
545 }
546}
547
548test "array concat of slices gives slice" {
549 comptime {
550 var a: []const u8 = "aoeu";
551 var b: []const u8 = "asdf";
552 const c = a ++ b;
553 try expect(std.mem.eql(u8, c, "aoeuasdf"));
554 }
555}
556
557test "comptime shlWithOverflow" {
558 const ct_shifted: u64 = comptime amt: {
559 var amt = @as(u64, 0);
560 _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
561 break :amt amt;
562 };
563
564 const rt_shifted: u64 = amt: {
565 var amt = @as(u64, 0);
566 _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
567 break :amt amt;
568 };
569
570 try expect(ct_shifted == rt_shifted);
571}
572
573test "runtime 128 bit integer division" {
574 var a: u128 = 152313999999999991610955792383;
575 var b: u128 = 10000000000000000000;
576 var c = a / b;
577 try expect(c == 15231399999);
578}
579
580pub const Info = struct {
581 version: u8,
582};
583
584pub const diamond_info = Info{ .version = 0 };
585
586test "comptime modification of const struct field" {
587 comptime {
588 var res = diamond_info;
589 res.version = 1;
590 try expect(diamond_info.version == 0);
591 try expect(res.version == 1);
592 }
593}
594
595test "pointer to type" {
596 comptime {
597 var T: type = i32;
598 try expect(T == i32);
599 var ptr = &T;
600 try expect(@TypeOf(ptr) == *type);
601 ptr.* = f32;
602 try expect(T == f32);
603 try expect(*T == *f32);
604 }
605}
606
607test "slice of type" {
608 comptime {
609 var types_array = [_]type{ i32, f64, type };
610 for (types_array) |T, i| {
611 switch (i) {
612 0 => try expect(T == i32),
613 1 => try expect(T == f64),
614 2 => try expect(T == type),
615 else => unreachable,
616 }
617 }
618 for (types_array[0..]) |T, i| {
619 switch (i) {
620 0 => try expect(T == i32),
621 1 => try expect(T == f64),
622 2 => try expect(T == type),
623 else => unreachable,
624 }
625 }
626 }
627}
628
629const Wrapper = struct {
630 T: type,
631};
632
633fn wrap(comptime T: type) Wrapper {
634 return Wrapper{ .T = T };
635}
636
637test "function which returns struct with type field causes implicit comptime" {
638 const ty = wrap(i32).T;
639 try expect(ty == i32);
640}
641
642test "call method with comptime pass-by-non-copying-value self parameter" {
643 const S = struct {
644 a: u8,
645
646 fn b(comptime s: @This()) u8 {
647 return s.a;
648 }
649 };
650
651 const s = S{ .a = 2 };
652 var b = s.b();
653 try expect(b == 2);
654}
655
656test "@tagName of @typeInfo" {
657 const str = @tagName(@typeInfo(u8));
658 try expect(std.mem.eql(u8, str, "Int"));
659}
660
661test "setting backward branch quota just before a generic fn call" {
662 @setEvalBranchQuota(1001);
663 loopNTimes(1001);
664}
665
666fn loopNTimes(comptime n: usize) void {
667 comptime var i = 0;
668 inline while (i < n) : (i += 1) {}
669}
670
671test "variable inside inline loop that has different types on different iterations" {
672 try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
673}
674
675fn testVarInsideInlineLoop(args: anytype) !void {
676 comptime var i = 0;
677 inline while (i < args.len) : (i += 1) {
678 const x = args[i];
679 if (i == 0) try expect(x);
680 if (i == 1) try expect(x == 42);
681 }
682}
683
684test "inline for with same type but different values" {
685 var res: usize = 0;
686 inline for ([_]type{ [2]u8, [1]u8, [2]u8 }) |T| {
687 var a: T = undefined;
688 res += a.len;
689 }
690 try expect(res == 5);
691}
692
693test "refer to the type of a generic function" {
694 const Func = fn (type) void;
695 const f: Func = doNothingWithType;
696 f(i32);
697}
698
699fn doNothingWithType(comptime T: type) void {}
700
701test "zero extend from u0 to u1" {
702 var zero_u0: u0 = 0;
703 var zero_u1: u1 = zero_u0;
704 try expect(zero_u1 == 0);
705}
706
707test "bit shift a u1" {
708 var x: u1 = 1;
709 var y = x << 0;
710 try expect(y == 1);
711}
712
713test "comptime pointer cast array and then slice" {
714 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
715
716 const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
717 const sliceA: []const u8 = ptrA[0..2];
718
719 const ptrB: [*]const u8 = &array;
720 const sliceB: []const u8 = ptrB[0..2];
721
722 try expect(sliceA[1] == 2);
723 try expect(sliceB[1] == 2);
724}
725
726test "slice bounds in comptime concatenation" {
727 const bs = comptime blk: {
728 const b = "........1........";
729 break :blk b[8..9];
730 };
731 const str = "" ++ bs;
732 try expect(str.len == 1);
733 try expect(std.mem.eql(u8, str, "1"));
734
735 const str2 = bs ++ "";
736 try expect(str2.len == 1);
737 try expect(std.mem.eql(u8, str2, "1"));
738}
739
740test "comptime bitwise operators" {
741 comptime {
742 try expect(3 & 1 == 1);
743 try expect(3 & -1 == 3);
744 try expect(-3 & -1 == -3);
745 try expect(3 | -1 == -1);
746 try expect(-3 | -1 == -1);
747 try expect(3 ^ -1 == -4);
748 try expect(-3 ^ -1 == 2);
749 try expect(~@as(i8, -1) == 0);
750 try expect(~@as(i128, -1) == 0);
751 try expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
752 try expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
753 try expect(~@as(u128, 0) == 0xffffffffffffffffffffffffffffffff);
754 }
755}
756
757test "*align(1) u16 is the same as *align(1:0:2) u16" {
758 comptime {
759 try expect(*align(1:0:2) u16 == *align(1) u16);
760 try expect(*align(2:0:2) u16 == *u16);
761 }
762}
763
764test "array concatenation forces comptime" {
765 var a = oneItem(3) ++ oneItem(4);
766 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
767}
768
769test "array multiplication forces comptime" {
770 var a = oneItem(3) ** scalar(2);
771 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
772}
773
774fn oneItem(x: i32) [1]i32 {
775 return [_]i32{x};
776}
777
778fn scalar(x: u32) u32 {
779 return x;
780}
781
782test "no undeclared identifier error in unanalyzed branches" {
783 if (false) {
784 lol_this_doesnt_exist = nonsense;
785 }
786}
787
788test "comptime assign int to optional int" {
789 comptime {
790 var x: ?i32 = null;
791 x = 2;
792 x.? *= 10;
793 try expectEqual(20, x.?);
794 }
795}
796
797test "return 0 from function that has u0 return type" {
798 const S = struct {
799 fn foo_zero() u0 {
800 return 0;
801 }
802 };
803 comptime {
804 if (S.foo_zero() != 0) {
805 @compileError("test failed");
806 }
807 }
808}
809
810test "two comptime calls with array default initialized to undefined" {
811 const S = struct {
812 const CrossTarget = struct {
813 dynamic_linker: DynamicLinker = DynamicLinker{},
814
815 pub fn parse() void {
816 var result: CrossTarget = .{};
817 result.getCpuArch();
818 }
819
820 pub fn getCpuArch(self: CrossTarget) void {}
821 };
822
823 const DynamicLinker = struct {
824 buffer: [255]u8 = undefined,
825 };
826 };
827
828 comptime {
829 S.CrossTarget.parse();
830 S.CrossTarget.parse();
831 }
832}
test/behavior/field_parent_ptr.zig created+41
...@@ -0,0 +1,41 @@
1const expect = @import("std").testing.expect;
2
3test "@fieldParentPtr non-first field" {
4 try testParentFieldPtr(&foo.c);
5 comptime try testParentFieldPtr(&foo.c);
6}
7
8test "@fieldParentPtr first field" {
9 try testParentFieldPtrFirst(&foo.a);
10 comptime try 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 try expect(c == &foo.c);
29
30 const base = @fieldParentPtr(Foo, "c", c);
31 try expect(base == &foo);
32 try expect(&base.c == c);
33}
34
35fn testParentFieldPtrFirst(a: *const bool) !void {
36 try expect(a == &foo.a);
37
38 const base = @fieldParentPtr(Foo, "a", a);
39 try expect(base == &foo);
40 try expect(&base.a == a);
41}
test/behavior/floatop.zig created+465
...@@ -0,0 +1,465 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const math = std.math;
4const pi = std.math.pi;
5const e = std.math.e;
6const Vector = std.meta.Vector;
7
8const epsilon = 0.000001;
9
10test "@sqrt" {
11 comptime try testSqrt();
12 try testSqrt();
13}
14
15fn testSqrt() !void {
16 {
17 var a: f16 = 4;
18 try expect(@sqrt(a) == 2);
19 }
20 {
21 var a: f32 = 9;
22 try expect(@sqrt(a) == 3);
23 var b: f32 = 1.1;
24 try expect(math.approxEqAbs(f32, @sqrt(b), 1.0488088481701516, epsilon));
25 }
26 {
27 var a: f64 = 25;
28 try expect(@sqrt(a) == 5);
29 }
30 {
31 const a: comptime_float = 25.0;
32 try expect(@sqrt(a) == 5.0);
33 }
34 // TODO https://github.com/ziglang/zig/issues/4026
35 //{
36 // var a: f128 = 49;
37 //try expect(@sqrt(a) == 7);
38 //}
39 {
40 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
41 var result = @sqrt(v);
42 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon));
43 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon));
44 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 3.3)), result[2], epsilon));
45 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon));
46 }
47}
48
49test "more @sqrt f16 tests" {
50 // TODO these are not all passing at comptime
51 try expect(@sqrt(@as(f16, 0.0)) == 0.0);
52 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 2.0)), 1.414214, epsilon));
53 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 3.6)), 1.897367, epsilon));
54 try expect(@sqrt(@as(f16, 4.0)) == 2.0);
55 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 7.539840)), 2.745877, epsilon));
56 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 19.230934)), 4.385309, epsilon));
57 try expect(@sqrt(@as(f16, 64.0)) == 8.0);
58 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 64.1)), 8.006248, epsilon));
59 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 8942.230469)), 94.563370, epsilon));
60
61 // special cases
62 try expect(math.isPositiveInf(@sqrt(@as(f16, math.inf(f16)))));
63 try expect(@sqrt(@as(f16, 0.0)) == 0.0);
64 try expect(@sqrt(@as(f16, -0.0)) == -0.0);
65 try expect(math.isNan(@sqrt(@as(f16, -1.0))));
66 try expect(math.isNan(@sqrt(@as(f16, math.nan(f16)))));
67}
68
69test "@sin" {
70 comptime try testSin();
71 try testSin();
72}
73
74fn testSin() !void {
75 // TODO test f128, and c_longdouble
76 // https://github.com/ziglang/zig/issues/4026
77 {
78 var a: f16 = 0;
79 try expect(@sin(a) == 0);
80 }
81 {
82 var a: f32 = 0;
83 try expect(@sin(a) == 0);
84 }
85 {
86 var a: f64 = 0;
87 try expect(@sin(a) == 0);
88 }
89 {
90 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
91 var result = @sin(v);
92 try expect(math.approxEqAbs(f32, @sin(@as(f32, 1.1)), result[0], epsilon));
93 try expect(math.approxEqAbs(f32, @sin(@as(f32, 2.2)), result[1], epsilon));
94 try expect(math.approxEqAbs(f32, @sin(@as(f32, 3.3)), result[2], epsilon));
95 try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon));
96 }
97}
98
99test "@cos" {
100 comptime try testCos();
101 try testCos();
102}
103
104fn testCos() !void {
105 // TODO test f128, and c_longdouble
106 // https://github.com/ziglang/zig/issues/4026
107 {
108 var a: f16 = 0;
109 try expect(@cos(a) == 1);
110 }
111 {
112 var a: f32 = 0;
113 try expect(@cos(a) == 1);
114 }
115 {
116 var a: f64 = 0;
117 try expect(@cos(a) == 1);
118 }
119 {
120 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
121 var result = @cos(v);
122 try expect(math.approxEqAbs(f32, @cos(@as(f32, 1.1)), result[0], epsilon));
123 try expect(math.approxEqAbs(f32, @cos(@as(f32, 2.2)), result[1], epsilon));
124 try expect(math.approxEqAbs(f32, @cos(@as(f32, 3.3)), result[2], epsilon));
125 try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon));
126 }
127}
128
129test "@exp" {
130 comptime try testExp();
131 try testExp();
132}
133
134fn testExp() !void {
135 // TODO test f128, and c_longdouble
136 // https://github.com/ziglang/zig/issues/4026
137 {
138 var a: f16 = 0;
139 try expect(@exp(a) == 1);
140 }
141 {
142 var a: f32 = 0;
143 try expect(@exp(a) == 1);
144 }
145 {
146 var a: f64 = 0;
147 try expect(@exp(a) == 1);
148 }
149 {
150 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
151 var result = @exp(v);
152 try expect(math.approxEqAbs(f32, @exp(@as(f32, 1.1)), result[0], epsilon));
153 try expect(math.approxEqAbs(f32, @exp(@as(f32, 2.2)), result[1], epsilon));
154 try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.3)), result[2], epsilon));
155 try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.4)), result[3], epsilon));
156 }
157}
158
159test "@exp2" {
160 comptime try testExp2();
161 try testExp2();
162}
163
164fn testExp2() !void {
165 // TODO test f128, and c_longdouble
166 // https://github.com/ziglang/zig/issues/4026
167 {
168 var a: f16 = 2;
169 try expect(@exp2(a) == 4);
170 }
171 {
172 var a: f32 = 2;
173 try expect(@exp2(a) == 4);
174 }
175 {
176 var a: f64 = 2;
177 try expect(@exp2(a) == 4);
178 }
179 {
180 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
181 var result = @exp2(v);
182 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 1.1)), result[0], epsilon));
183 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 2.2)), result[1], epsilon));
184 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.3)), result[2], epsilon));
185 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.4)), result[3], epsilon));
186 }
187}
188
189test "@log" {
190 // Old musl (and glibc?), and our current math.ln implementation do not return 1
191 // so also accept those values.
192 comptime try testLog();
193 try testLog();
194}
195
196fn testLog() !void {
197 // TODO test f128, and c_longdouble
198 // https://github.com/ziglang/zig/issues/4026
199 {
200 var a: f16 = e;
201 try expect(math.approxEqAbs(f16, @log(a), 1, epsilon));
202 }
203 {
204 var a: f32 = e;
205 try expect(@log(a) == 1 or @log(a) == @bitCast(f32, @as(u32, 0x3f7fffff)));
206 }
207 {
208 var a: f64 = e;
209 try expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));
210 }
211 {
212 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
213 var result = @log(v);
214 try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon));
215 try expect(math.approxEqAbs(f32, @log(@as(f32, 2.2)), result[1], epsilon));
216 try expect(math.approxEqAbs(f32, @log(@as(f32, 0.3)), result[2], epsilon));
217 try expect(math.approxEqAbs(f32, @log(@as(f32, 0.4)), result[3], epsilon));
218 }
219}
220
221test "@log2" {
222 comptime try testLog2();
223 try testLog2();
224}
225
226fn testLog2() !void {
227 // TODO test f128, and c_longdouble
228 // https://github.com/ziglang/zig/issues/4026
229 {
230 var a: f16 = 4;
231 try expect(@log2(a) == 2);
232 }
233 {
234 var a: f32 = 4;
235 try expect(@log2(a) == 2);
236 }
237 {
238 var a: f64 = 4;
239 try expect(@log2(a) == 2);
240 }
241 {
242 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
243 var result = @log2(v);
244 try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon));
245 try expect(math.approxEqAbs(f32, @log2(@as(f32, 2.2)), result[1], epsilon));
246 try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.3)), result[2], epsilon));
247 try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.4)), result[3], epsilon));
248 }
249}
250
251test "@log10" {
252 comptime try testLog10();
253 try testLog10();
254}
255
256fn testLog10() !void {
257 // TODO test f128, and c_longdouble
258 // https://github.com/ziglang/zig/issues/4026
259 {
260 var a: f16 = 100;
261 try expect(@log10(a) == 2);
262 }
263 {
264 var a: f32 = 100;
265 try expect(@log10(a) == 2);
266 }
267 {
268 var a: f64 = 1000;
269 try expect(@log10(a) == 3);
270 }
271 {
272 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
273 var result = @log10(v);
274 try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon));
275 try expect(math.approxEqAbs(f32, @log10(@as(f32, 2.2)), result[1], epsilon));
276 try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.3)), result[2], epsilon));
277 try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.4)), result[3], epsilon));
278 }
279}
280
281test "@fabs" {
282 comptime try testFabs();
283 try testFabs();
284}
285
286fn testFabs() !void {
287 // TODO test f128, and c_longdouble
288 // https://github.com/ziglang/zig/issues/4026
289 {
290 var a: f16 = -2.5;
291 var b: f16 = 2.5;
292 try expect(@fabs(a) == 2.5);
293 try expect(@fabs(b) == 2.5);
294 }
295 {
296 var a: f32 = -2.5;
297 var b: f32 = 2.5;
298 try expect(@fabs(a) == 2.5);
299 try expect(@fabs(b) == 2.5);
300 }
301 {
302 var a: f64 = -2.5;
303 var b: f64 = 2.5;
304 try expect(@fabs(a) == 2.5);
305 try expect(@fabs(b) == 2.5);
306 }
307 {
308 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
309 var result = @fabs(v);
310 try expect(math.approxEqAbs(f32, @fabs(@as(f32, 1.1)), result[0], epsilon));
311 try expect(math.approxEqAbs(f32, @fabs(@as(f32, -2.2)), result[1], epsilon));
312 try expect(math.approxEqAbs(f32, @fabs(@as(f32, 0.3)), result[2], epsilon));
313 try expect(math.approxEqAbs(f32, @fabs(@as(f32, -0.4)), result[3], epsilon));
314 }
315}
316
317test "@floor" {
318 comptime try testFloor();
319 try testFloor();
320}
321
322fn testFloor() !void {
323 // TODO test f128, and c_longdouble
324 // https://github.com/ziglang/zig/issues/4026
325 {
326 var a: f16 = 2.1;
327 try expect(@floor(a) == 2);
328 }
329 {
330 var a: f32 = 2.1;
331 try expect(@floor(a) == 2);
332 }
333 {
334 var a: f64 = 3.5;
335 try expect(@floor(a) == 3);
336 }
337 {
338 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
339 var result = @floor(v);
340 try expect(math.approxEqAbs(f32, @floor(@as(f32, 1.1)), result[0], epsilon));
341 try expect(math.approxEqAbs(f32, @floor(@as(f32, -2.2)), result[1], epsilon));
342 try expect(math.approxEqAbs(f32, @floor(@as(f32, 0.3)), result[2], epsilon));
343 try expect(math.approxEqAbs(f32, @floor(@as(f32, -0.4)), result[3], epsilon));
344 }
345}
346
347test "@ceil" {
348 comptime try testCeil();
349 try testCeil();
350}
351
352fn testCeil() !void {
353 // TODO test f128, and c_longdouble
354 // https://github.com/ziglang/zig/issues/4026
355 {
356 var a: f16 = 2.1;
357 try expect(@ceil(a) == 3);
358 }
359 {
360 var a: f32 = 2.1;
361 try expect(@ceil(a) == 3);
362 }
363 {
364 var a: f64 = 3.5;
365 try expect(@ceil(a) == 4);
366 }
367 {
368 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
369 var result = @ceil(v);
370 try expect(math.approxEqAbs(f32, @ceil(@as(f32, 1.1)), result[0], epsilon));
371 try expect(math.approxEqAbs(f32, @ceil(@as(f32, -2.2)), result[1], epsilon));
372 try expect(math.approxEqAbs(f32, @ceil(@as(f32, 0.3)), result[2], epsilon));
373 try expect(math.approxEqAbs(f32, @ceil(@as(f32, -0.4)), result[3], epsilon));
374 }
375}
376
377test "@trunc" {
378 comptime try testTrunc();
379 try testTrunc();
380}
381
382fn testTrunc() !void {
383 // TODO test f128, and c_longdouble
384 // https://github.com/ziglang/zig/issues/4026
385 {
386 var a: f16 = 2.1;
387 try expect(@trunc(a) == 2);
388 }
389 {
390 var a: f32 = 2.1;
391 try expect(@trunc(a) == 2);
392 }
393 {
394 var a: f64 = -3.5;
395 try expect(@trunc(a) == -3);
396 }
397 {
398 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
399 var result = @trunc(v);
400 try expect(math.approxEqAbs(f32, @trunc(@as(f32, 1.1)), result[0], epsilon));
401 try expect(math.approxEqAbs(f32, @trunc(@as(f32, -2.2)), result[1], epsilon));
402 try expect(math.approxEqAbs(f32, @trunc(@as(f32, 0.3)), result[2], epsilon));
403 try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));
404 }
405}
406
407test "floating point comparisons" {
408 try testFloatComparisons();
409 comptime try testFloatComparisons();
410}
411
412fn testFloatComparisons() !void {
413 inline for ([_]type{ f16, f32, f64, f128 }) |ty| {
414 // No decimal part
415 {
416 const x: ty = 1.0;
417 try expect(x == 1);
418 try expect(x != 0);
419 try expect(x > 0);
420 try expect(x < 2);
421 try expect(x >= 1);
422 try expect(x <= 1);
423 }
424 // Non-zero decimal part
425 {
426 const x: ty = 1.5;
427 try expect(x != 1);
428 try expect(x != 2);
429 try expect(x > 1);
430 try expect(x < 2);
431 try expect(x >= 1);
432 try expect(x <= 2);
433 }
434 }
435}
436
437test "different sized float comparisons" {
438 try testDifferentSizedFloatComparisons();
439 comptime try testDifferentSizedFloatComparisons();
440}
441
442fn testDifferentSizedFloatComparisons() !void {
443 var a: f16 = 1;
444 var b: f64 = 2;
445 try expect(a < b);
446}
447
448// TODO This is waiting on library support for the Windows build (not sure why the other's don't need it)
449//test "@nearbyint" {
450// comptime testNearbyInt();
451// testNearbyInt();
452//}
453
454//fn testNearbyInt() void {
455// // TODO test f16, f128, and c_longdouble
456// // https://github.com/ziglang/zig/issues/4026
457// {
458// var a: f32 = 2.1;
459// try expect(@nearbyint(a) == 2);
460// }
461// {
462// var a: f64 = -3.75;
463// try expect(@nearbyint(a) == -4);
464// }
465//}
test/behavior/fn.zig created+287
...@@ -0,0 +1,287 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const testing = std.testing;
4const expect = testing.expect;
5const expectEqual = testing.expectEqual;
6
7test "params" {
8 try expect(testParamsAdd(22, 11) == 33);
9}
10fn testParamsAdd(a: i32, b: i32) i32 {
11 return a + b;
12}
13
14test "local variables" {
15 testLocVars(2);
16}
17fn testLocVars(b: i32) void {
18 const a: i32 = 1;
19 if (a + b != 3) unreachable;
20}
21
22test "void parameters" {
23 try voidFun(1, void{}, 2, {});
24}
25fn voidFun(a: i32, b: void, c: i32, d: void) !void {
26 const v = b;
27 const vv: void = if (a == 1) v else {};
28 try expect(a + c == 3);
29 return vv;
30}
31
32test "mutable local variables" {
33 var zero: i32 = 0;
34 try expect(zero == 0);
35
36 var i = @as(i32, 0);
37 while (i != 3) {
38 i += 1;
39 }
40 try expect(i == 3);
41}
42
43test "separate block scopes" {
44 {
45 const no_conflict: i32 = 5;
46 try expect(no_conflict == 5);
47 }
48
49 const c = x: {
50 const no_conflict = @as(i32, 10);
51 break :x no_conflict;
52 };
53 try expect(c == 10);
54}
55
56test "call function with empty string" {
57 acceptsString("");
58}
59
60fn acceptsString(foo: []u8) void {}
61
62fn @"weird function name"() i32 {
63 return 1234;
64}
65test "weird function name" {
66 try expect(@"weird function name"() == 1234);
67}
68
69test "implicit cast function unreachable return" {
70 wantsFnWithVoid(fnWithUnreachable);
71}
72
73fn wantsFnWithVoid(f: fn () void) void {}
74
75fn fnWithUnreachable() noreturn {
76 unreachable;
77}
78
79test "function pointers" {
80 const fns = [_]@TypeOf(fn1){
81 fn1,
82 fn2,
83 fn3,
84 fn4,
85 };
86 for (fns) |f, i| {
87 try expect(f() == @intCast(u32, i) + 5);
88 }
89}
90fn fn1() u32 {
91 return 5;
92}
93fn fn2() u32 {
94 return 6;
95}
96fn fn3() u32 {
97 return 7;
98}
99fn fn4() u32 {
100 return 8;
101}
102
103test "number literal as an argument" {
104 try numberLiteralArg(3);
105 comptime try numberLiteralArg(3);
106}
107
108fn numberLiteralArg(a: anytype) !void {
109 try expect(a == 3);
110}
111
112test "assign inline fn to const variable" {
113 const a = inlineFn;
114 a();
115}
116
117fn inlineFn() callconv(.Inline) void {}
118
119test "pass by non-copying value" {
120 try expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
121}
122
123const Point = struct {
124 x: i32,
125 y: i32,
126};
127
128fn addPointCoords(pt: Point) i32 {
129 return pt.x + pt.y;
130}
131
132test "pass by non-copying value through var arg" {
133 try expect((try addPointCoordsVar(Point{ .x = 1, .y = 2 })) == 3);
134}
135
136fn addPointCoordsVar(pt: anytype) !i32 {
137 comptime try expect(@TypeOf(pt) == Point);
138 return pt.x + pt.y;
139}
140
141test "pass by non-copying value as method" {
142 var pt = Point2{ .x = 1, .y = 2 };
143 try expect(pt.addPointCoords() == 3);
144}
145
146const Point2 = struct {
147 x: i32,
148 y: i32,
149
150 fn addPointCoords(self: Point2) i32 {
151 return self.x + self.y;
152 }
153};
154
155test "pass by non-copying value as method, which is generic" {
156 var pt = Point3{ .x = 1, .y = 2 };
157 try expect(pt.addPointCoords(i32) == 3);
158}
159
160const Point3 = struct {
161 x: i32,
162 y: i32,
163
164 fn addPointCoords(self: Point3, comptime T: type) i32 {
165 return self.x + self.y;
166 }
167};
168
169test "pass by non-copying value as method, at comptime" {
170 comptime {
171 var pt = Point2{ .x = 1, .y = 2 };
172 try expect(pt.addPointCoords() == 3);
173 }
174}
175
176fn outer(y: u32) fn (u32) u32 {
177 const Y = @TypeOf(y);
178 const st = struct {
179 fn get(z: u32) u32 {
180 return z + @sizeOf(Y);
181 }
182 };
183 return st.get;
184}
185
186test "return inner function which references comptime variable of outer function" {
187 var func = outer(10);
188 try expect(func(3) == 7);
189}
190
191test "extern struct with stdcallcc fn pointer" {
192 const S = extern struct {
193 ptr: fn () callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32,
194
195 fn foo() callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32 {
196 return 1234;
197 }
198 };
199
200 var s: S = undefined;
201 s.ptr = S.foo;
202 try expect(s.ptr() == 1234);
203}
204
205test "implicit cast fn call result to optional in field result" {
206 const S = struct {
207 fn entry() !void {
208 var x = Foo{
209 .field = optionalPtr(),
210 };
211 try expect(x.field.?.* == 999);
212 }
213
214 const glob: i32 = 999;
215
216 fn optionalPtr() *const i32 {
217 return &glob;
218 }
219
220 const Foo = struct {
221 field: ?*const i32,
222 };
223 };
224 try S.entry();
225 comptime try S.entry();
226}
227
228test "discard the result of a function that returns a struct" {
229 const S = struct {
230 fn entry() void {
231 _ = func();
232 }
233
234 fn func() Foo {
235 return undefined;
236 }
237
238 const Foo = struct {
239 a: u64,
240 b: u64,
241 };
242 };
243 S.entry();
244 comptime S.entry();
245}
246
247test "function call with anon list literal" {
248 const S = struct {
249 fn doTheTest() !void {
250 try consumeVec(.{ 9, 8, 7 });
251 }
252
253 fn consumeVec(vec: [3]f32) !void {
254 try expect(vec[0] == 9);
255 try expect(vec[1] == 8);
256 try expect(vec[2] == 7);
257 }
258 };
259 try S.doTheTest();
260 comptime try S.doTheTest();
261}
262
263test "ability to give comptime types and non comptime types to same parameter" {
264 const S = struct {
265 fn doTheTest() !void {
266 var x: i32 = 1;
267 try expect(foo(x) == 10);
268 try expect(foo(i32) == 20);
269 }
270
271 fn foo(arg: anytype) i32 {
272 if (@typeInfo(@TypeOf(arg)) == .Type and arg == i32) return 20;
273 return 9 + arg;
274 }
275 };
276 try S.doTheTest();
277 comptime try S.doTheTest();
278}
279
280test "function with inferred error set but returning no error" {
281 const S = struct {
282 fn foo() !void {}
283 };
284
285 const return_ty = @typeInfo(@TypeOf(S.foo)).Fn.return_type.?;
286 try expectEqual(0, @typeInfo(@typeInfo(return_ty).ErrorUnion.error_set).ErrorSet.?.len);
287}
test/behavior/fn_delegation.zig created+39
...@@ -0,0 +1,39 @@
1const expect = @import("std").testing.expect;
2
3const Foo = struct {
4 a: u64 = 10,
5
6 fn one(self: Foo) u64 {
7 return self.a + 1;
8 }
9
10 const two = __two;
11
12 fn __two(self: Foo) u64 {
13 return self.a + 2;
14 }
15
16 const three = __three;
17
18 const four = custom(Foo, 4);
19};
20
21fn __three(self: Foo) u64 {
22 return self.a + 3;
23}
24
25fn custom(comptime T: type, comptime num: u64) fn (T) u64 {
26 return struct {
27 fn function(self: T) u64 {
28 return self.a + num;
29 }
30 }.function;
31}
32
33test "fn delegation" {
34 const foo = Foo{};
35 try expect(foo.one() == 11);
36 try expect(foo.two() == 12);
37 try expect(foo.three() == 13);
38 try expect(foo.four() == 14);
39}
test/behavior/fn_in_struct_in_comptime.zig created+17
...@@ -0,0 +1,17 @@
1const expect = @import("std").testing.expect;
2
3fn get_foo() fn (*u8) usize {
4 comptime {
5 return struct {
6 fn func(ptr: *u8) usize {
7 var u = @ptrToInt(ptr);
8 return u;
9 }
10 }.func;
11 }
12}
13
14test "define a function in an anonymous struct in comptime" {
15 const foo = get_foo();
16 try expect(foo(@intToPtr(*u8, 12345)) == 12345);
17}
test/behavior/for.zig created+172
...@@ -0,0 +1,172 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const mem = std.mem;
5
6test "continue in for loop" {
7 const array = [_]i32{
8 1,
9 2,
10 3,
11 4,
12 5,
13 };
14 var sum: i32 = 0;
15 for (array) |x| {
16 sum += x;
17 if (x < 3) {
18 continue;
19 }
20 break;
21 }
22 if (sum != 6) unreachable;
23}
24
25test "for loop with pointer elem var" {
26 const source = "abcdefg";
27 var target: [source.len]u8 = undefined;
28 mem.copy(u8, target[0..], source);
29 mangleString(target[0..]);
30 try expect(mem.eql(u8, &target, "bcdefgh"));
31
32 for (source) |*c, i|
33 try expect(@TypeOf(c) == *const u8);
34 for (target) |*c, i|
35 try expect(@TypeOf(c) == *u8);
36}
37
38fn mangleString(s: []u8) void {
39 for (s) |*c| {
40 c.* += 1;
41 }
42}
43
44test "basic for loop" {
45 const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
46
47 var buffer: [expected_result.len]u8 = undefined;
48 var buf_index: usize = 0;
49
50 const array = [_]u8{ 9, 8, 7, 6 };
51 for (array) |item| {
52 buffer[buf_index] = item;
53 buf_index += 1;
54 }
55 for (array) |item, index| {
56 buffer[buf_index] = @intCast(u8, index);
57 buf_index += 1;
58 }
59 const array_ptr = &array;
60 for (array_ptr) |item| {
61 buffer[buf_index] = item;
62 buf_index += 1;
63 }
64 for (array_ptr) |item, index| {
65 buffer[buf_index] = @intCast(u8, index);
66 buf_index += 1;
67 }
68 const unknown_size: []const u8 = &array;
69 for (unknown_size) |item| {
70 buffer[buf_index] = item;
71 buf_index += 1;
72 }
73 for (unknown_size) |item, index| {
74 buffer[buf_index] = @intCast(u8, index);
75 buf_index += 1;
76 }
77
78 try expect(mem.eql(u8, buffer[0..buf_index], &expected_result));
79}
80
81test "break from outer for loop" {
82 try testBreakOuter();
83 comptime try testBreakOuter();
84}
85
86fn testBreakOuter() !void {
87 var array = "aoeu";
88 var count: usize = 0;
89 outer: for (array) |_| {
90 for (array) |_| {
91 count += 1;
92 break :outer;
93 }
94 }
95 try expect(count == 1);
96}
97
98test "continue outer for loop" {
99 try testContinueOuter();
100 comptime try testContinueOuter();
101}
102
103fn testContinueOuter() !void {
104 var array = "aoeu";
105 var counter: usize = 0;
106 outer: for (array) |_| {
107 for (array) |_| {
108 counter += 1;
109 continue :outer;
110 }
111 }
112 try expect(counter == array.len);
113}
114
115test "2 break statements and an else" {
116 const S = struct {
117 fn entry(t: bool, f: bool) !void {
118 var buf: [10]u8 = undefined;
119 var ok = false;
120 ok = for (buf) |item| {
121 if (f) break false;
122 if (t) break true;
123 } else false;
124 try expect(ok);
125 }
126 };
127 try S.entry(true, false);
128 comptime try S.entry(true, false);
129}
130
131test "for with null and T peer types and inferred result location type" {
132 const S = struct {
133 fn doTheTest(slice: []const u8) !void {
134 if (for (slice) |item| {
135 if (item == 10) {
136 break item;
137 }
138 } else null) |v| {
139 @panic("fail");
140 }
141 }
142 };
143 try S.doTheTest(&[_]u8{ 1, 2 });
144 comptime try S.doTheTest(&[_]u8{ 1, 2 });
145}
146
147test "for copies its payload" {
148 const S = struct {
149 fn doTheTest() !void {
150 var x = [_]usize{ 1, 2, 3 };
151 for (x) |value, i| {
152 // Modify the original array
153 x[i] += 99;
154 try expectEqual(value, i + 1);
155 }
156 }
157 };
158 try S.doTheTest();
159 comptime try S.doTheTest();
160}
161
162test "for on slice with allowzero ptr" {
163 const S = struct {
164 fn doTheTest(slice: []const u8) !void {
165 var ptr = @ptrCast([*]allowzero const u8, slice.ptr)[0..slice.len];
166 for (ptr) |x, i| try expect(x == i + 1);
167 for (ptr) |*x, i| try expect(x.* == i + 1);
168 }
169 };
170 try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
171 comptime try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
172}
test/behavior/generics.zig created+169
...@@ -0,0 +1,169 @@
1const std = @import("std");
2const testing = std.testing;
3const expect = testing.expect;
4const expectEqual = testing.expectEqual;
5
6test "simple generic fn" {
7 try expect(max(i32, 3, -1) == 3);
8 try expect(max(f32, 0.123, 0.456) == 0.456);
9 try expect(add(2, 3) == 5);
10}
11
12fn max(comptime T: type, a: T, b: T) T {
13 return if (a > b) a else b;
14}
15
16fn add(comptime a: i32, b: i32) i32 {
17 return (comptime a) + b;
18}
19
20const the_max = max(u32, 1234, 5678);
21test "compile time generic eval" {
22 try expect(the_max == 5678);
23}
24
25fn gimmeTheBigOne(a: u32, b: u32) u32 {
26 return max(u32, a, b);
27}
28
29fn shouldCallSameInstance(a: u32, b: u32) u32 {
30 return max(u32, a, b);
31}
32
33fn sameButWithFloats(a: f64, b: f64) f64 {
34 return max(f64, a, b);
35}
36
37test "fn with comptime args" {
38 try expect(gimmeTheBigOne(1234, 5678) == 5678);
39 try expect(shouldCallSameInstance(34, 12) == 34);
40 try expect(sameButWithFloats(0.43, 0.49) == 0.49);
41}
42
43test "var params" {
44 try expect(max_i32(12, 34) == 34);
45 try expect(max_f64(1.2, 3.4) == 3.4);
46}
47
48comptime {
49 try expect(max_i32(12, 34) == 34);
50 try expect(max_f64(1.2, 3.4) == 3.4);
51}
52
53fn max_var(a: anytype, b: anytype) @TypeOf(a + b) {
54 return if (a > b) a else b;
55}
56
57fn max_i32(a: i32, b: i32) i32 {
58 return max_var(a, b);
59}
60
61fn max_f64(a: f64, b: f64) f64 {
62 return max_var(a, b);
63}
64
65pub fn List(comptime T: type) type {
66 return SmallList(T, 8);
67}
68
69pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
70 return struct {
71 items: []T,
72 length: usize,
73 prealloc_items: [STATIC_SIZE]T,
74 };
75}
76
77test "function with return type type" {
78 var list: List(i32) = undefined;
79 var list2: List(i32) = undefined;
80 list.length = 10;
81 list2.length = 10;
82 try expect(list.prealloc_items.len == 8);
83 try expect(list2.prealloc_items.len == 8);
84}
85
86test "generic struct" {
87 var a1 = GenNode(i32){
88 .value = 13,
89 .next = null,
90 };
91 var b1 = GenNode(bool){
92 .value = true,
93 .next = null,
94 };
95 try expect(a1.value == 13);
96 try expect(a1.value == a1.getVal());
97 try expect(b1.getVal());
98}
99fn GenNode(comptime T: type) type {
100 return struct {
101 value: T,
102 next: ?*GenNode(T),
103 fn getVal(n: *const GenNode(T)) T {
104 return n.value;
105 }
106 };
107}
108
109test "const decls in struct" {
110 try expect(GenericDataThing(3).count_plus_one == 4);
111}
112fn GenericDataThing(comptime count: isize) type {
113 return struct {
114 const count_plus_one = count + 1;
115 };
116}
117
118test "use generic param in generic param" {
119 try expect(aGenericFn(i32, 3, 4) == 7);
120}
121fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
122 return a + b;
123}
124
125test "generic fn with implicit cast" {
126 try expect(getFirstByte(u8, &[_]u8{13}) == 13);
127 try expect(getFirstByte(u16, &[_]u16{
128 0,
129 13,
130 }) == 0);
131}
132fn getByte(ptr: ?*const u8) u8 {
133 return ptr.?.*;
134}
135fn getFirstByte(comptime T: type, mem: []const T) u8 {
136 return getByte(@ptrCast(*const u8, &mem[0]));
137}
138
139const foos = [_]fn (anytype) bool{
140 foo1,
141 foo2,
142};
143
144fn foo1(arg: anytype) bool {
145 return arg;
146}
147fn foo2(arg: anytype) bool {
148 return !arg;
149}
150
151test "array of generic fns" {
152 try expect(foos[0](true));
153 try expect(!foos[1](true));
154}
155
156test "generic fn keeps non-generic parameter types" {
157 const A = 128;
158
159 const S = struct {
160 fn f(comptime T: type, s: []T) !void {
161 try expect(A != @typeInfo(@TypeOf(s)).Pointer.alignment);
162 }
163 };
164
165 // The compiler monomorphizes `S.f` for `T=u8` on its first use, check that
166 // `x` type not affect `s` parameter type.
167 var x: [16]u8 align(A) = undefined;
168 try S.f(u8, &x);
169}
test/behavior/hasdecl.zig created+21
...@@ -0,0 +1,21 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const Foo = @import("hasdecl/foo.zig");
5
6const Bar = struct {
7 nope: i32,
8
9 const hi = 1;
10 pub var blah = "xxx";
11};
12
13test "@hasDecl" {
14 try expect(@hasDecl(Foo, "public_thing"));
15 try expect(!@hasDecl(Foo, "private_thing"));
16 try expect(!@hasDecl(Foo, "no_thing"));
17
18 try expect(@hasDecl(Bar, "hi"));
19 try expect(@hasDecl(Bar, "blah"));
20 try expect(!@hasDecl(Bar, "nope"));
21}
test/behavior/hasdecl/foo.zig created+2
...@@ -0,0 +1,2 @@
1pub const public_thing = 42;
2const private_thing = 666;
test/behavior/hasfield.zig created+37
...@@ -0,0 +1,37 @@
1const expect = @import("std").testing.expect;
2const builtin = @import("builtin");
3
4test "@hasField" {
5 const struc = struct {
6 a: i32,
7 b: []u8,
8
9 pub const nope = 1;
10 };
11 try expect(@hasField(struc, "a") == true);
12 try expect(@hasField(struc, "b") == true);
13 try expect(@hasField(struc, "non-existant") == false);
14 try expect(@hasField(struc, "nope") == false);
15
16 const unin = union {
17 a: u64,
18 b: []u16,
19
20 pub const nope = 1;
21 };
22 try expect(@hasField(unin, "a") == true);
23 try expect(@hasField(unin, "b") == true);
24 try expect(@hasField(unin, "non-existant") == false);
25 try expect(@hasField(unin, "nope") == false);
26
27 const enm = enum {
28 a,
29 b,
30
31 pub const nope = 1;
32 };
33 try expect(@hasField(enm, "a") == true);
34 try expect(@hasField(enm, "b") == true);
35 try expect(@hasField(enm, "non-existant") == false);
36 try expect(@hasField(enm, "nope") == false);
37}
test/behavior/if.zig created+109
...@@ -0,0 +1,109 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4
5test "if statements" {
6 shouldBeEqual(1, 1);
7 firstEqlThird(2, 1, 2);
8}
9fn shouldBeEqual(a: i32, b: i32) void {
10 if (a != b) {
11 unreachable;
12 } else {
13 return;
14 }
15}
16fn firstEqlThird(a: i32, b: i32, c: i32) void {
17 if (a == b) {
18 unreachable;
19 } else if (b == c) {
20 unreachable;
21 } else if (a == c) {
22 return;
23 } else {
24 unreachable;
25 }
26}
27
28test "else if expression" {
29 try expect(elseIfExpressionF(1) == 1);
30}
31fn elseIfExpressionF(c: u8) u8 {
32 if (c == 0) {
33 return 0;
34 } else if (c == 1) {
35 return 1;
36 } else {
37 return @as(u8, 2);
38 }
39}
40
41// #2297
42var global_with_val: anyerror!u32 = 0;
43var global_with_err: anyerror!u32 = error.SomeError;
44
45test "unwrap mutable global var" {
46 if (global_with_val) |v| {
47 try expect(v == 0);
48 } else |e| {
49 unreachable;
50 }
51 if (global_with_err) |_| {
52 unreachable;
53 } else |e| {
54 try expect(e == error.SomeError);
55 }
56}
57
58test "labeled break inside comptime if inside runtime if" {
59 var answer: i32 = 0;
60 var c = true;
61 if (c) {
62 answer = if (true) blk: {
63 break :blk @as(i32, 42);
64 };
65 }
66 try expect(answer == 42);
67}
68
69test "const result loc, runtime if cond, else unreachable" {
70 const Num = enum {
71 One,
72 Two,
73 };
74
75 var t = true;
76 const x = if (t) Num.Two else unreachable;
77 try expect(x == .Two);
78}
79
80test "if prongs cast to expected type instead of peer type resolution" {
81 const S = struct {
82 fn doTheTest(f: bool) !void {
83 var x: i32 = 0;
84 x = if (f) 1 else 2;
85 try expect(x == 2);
86
87 var b = true;
88 const y: i32 = if (b) 1 else 2;
89 try expect(y == 1);
90 }
91 };
92 try S.doTheTest(false);
93 comptime try S.doTheTest(false);
94}
95
96test "while copies its payload" {
97 const S = struct {
98 fn doTheTest() !void {
99 var tmp: ?i32 = 10;
100 if (tmp) |value| {
101 // Modify the original variable
102 tmp = null;
103 try expectEqual(@as(i32, 10), value);
104 } else unreachable;
105 }
106 };
107 try S.doTheTest();
108 comptime try S.doTheTest();
109}
test/behavior/import.zig created+22
...@@ -0,0 +1,22 @@
1const expect = @import("std").testing.expect;
2const expectEqual = @import("std").testing.expectEqual;
3const a_namespace = @import("import/a_namespace.zig");
4
5test "call fn via namespace lookup" {
6 try expectEqual(@as(i32, 1234), a_namespace.foo());
7}
8
9test "importing the same thing gives the same import" {
10 try expect(@import("std") == @import("std"));
11}
12
13test "import in non-toplevel scope" {
14 const S = struct {
15 usingnamespace @import("import/a_namespace.zig");
16 };
17 try expectEqual(@as(i32, 1234), S.foo());
18}
19
20test "import empty file" {
21 const empty = @import("import/empty.zig");
22}
test/behavior/import/a_namespace.zig created+3
...@@ -0,0 +1,3 @@
1pub fn foo() i32 {
2 return 1234;
3}
test/behavior/import/empty.zig created
test/behavior/incomplete_struct_param_tld.zig created+30
...@@ -0,0 +1,30 @@
1const expect = @import("std").testing.expect;
2
3const A = struct {
4 b: B,
5};
6
7const B = struct {
8 c: C,
9};
10
11const C = struct {
12 x: i32,
13
14 fn d(c: *const C) i32 {
15 return c.x;
16 }
17};
18
19fn foo(a: A) i32 {
20 return a.b.c.d();
21}
22
23test "incomplete struct param top level declaration" {
24 const a = A{
25 .b = B{
26 .c = C{ .x = 13 },
27 },
28 };
29 try expect(foo(a) == 13);
30}
test/behavior/inttoptr.zig created+22
...@@ -0,0 +1,22 @@
1test "casting random address to function pointer" {
2 randomAddressToFunction();
3 comptime randomAddressToFunction();
4}
5
6fn randomAddressToFunction() void {
7 var addr: usize = 0xdeadbeef;
8 var ptr = @intToPtr(fn () void, addr);
9}
10
11test "mutate through ptr initialized with constant intToPtr value" {
12 forceCompilerAnalyzeBranchHardCodedPtrDereference(false);
13}
14
15fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
16 const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef);
17 if (x) {
18 hardCodedP.* = hardCodedP.* | 10;
19 } else {
20 return;
21 }
22}
test/behavior/ir_block_deps.zig created+21
...@@ -0,0 +1,21 @@
1const expect = @import("std").testing.expect;
2
3fn foo(id: u64) !i32 {
4 return switch (id) {
5 1 => getErrInt(),
6 2 => {
7 const size = try getErrInt();
8 return try getErrInt();
9 },
10 else => error.ItBroke,
11 };
12}
13
14fn getErrInt() anyerror!i32 {
15 return 0;
16}
17
18test "ir block deps" {
19 try expect((foo(1) catch unreachable) == 0);
20 try expect((foo(2) catch unreachable) == 0);
21}
test/behavior/math.zig created+872
...@@ -0,0 +1,872 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const expectEqualSlices = std.testing.expectEqualSlices;
5const maxInt = std.math.maxInt;
6const minInt = std.math.minInt;
7const mem = std.mem;
8
9test "division" {
10 try testDivision();
11 comptime try testDivision();
12}
13fn testDivision() !void {
14 try expect(div(u32, 13, 3) == 4);
15 try expect(div(f16, 1.0, 2.0) == 0.5);
16 try expect(div(f32, 1.0, 2.0) == 0.5);
17
18 try expect(divExact(u32, 55, 11) == 5);
19 try expect(divExact(i32, -55, 11) == -5);
20 try expect(divExact(f16, 55.0, 11.0) == 5.0);
21 try expect(divExact(f16, -55.0, 11.0) == -5.0);
22 try expect(divExact(f32, 55.0, 11.0) == 5.0);
23 try expect(divExact(f32, -55.0, 11.0) == -5.0);
24
25 try expect(divFloor(i32, 5, 3) == 1);
26 try expect(divFloor(i32, -5, 3) == -2);
27 try expect(divFloor(f16, 5.0, 3.0) == 1.0);
28 try expect(divFloor(f16, -5.0, 3.0) == -2.0);
29 try expect(divFloor(f32, 5.0, 3.0) == 1.0);
30 try expect(divFloor(f32, -5.0, 3.0) == -2.0);
31 try expect(divFloor(i32, -0x80000000, -2) == 0x40000000);
32 try expect(divFloor(i32, 0, -0x80000000) == 0);
33 try expect(divFloor(i32, -0x40000001, 0x40000000) == -2);
34 try expect(divFloor(i32, -0x80000000, 1) == -0x80000000);
35 try expect(divFloor(i32, 10, 12) == 0);
36 try expect(divFloor(i32, -14, 12) == -2);
37 try expect(divFloor(i32, -2, 12) == -1);
38
39 try expect(divTrunc(i32, 5, 3) == 1);
40 try expect(divTrunc(i32, -5, 3) == -1);
41 try expect(divTrunc(f16, 5.0, 3.0) == 1.0);
42 try expect(divTrunc(f16, -5.0, 3.0) == -1.0);
43 try expect(divTrunc(f32, 5.0, 3.0) == 1.0);
44 try expect(divTrunc(f32, -5.0, 3.0) == -1.0);
45 try expect(divTrunc(f64, 5.0, 3.0) == 1.0);
46 try expect(divTrunc(f64, -5.0, 3.0) == -1.0);
47 try expect(divTrunc(i32, 10, 12) == 0);
48 try expect(divTrunc(i32, -14, 12) == -1);
49 try expect(divTrunc(i32, -2, 12) == 0);
50
51 try expect(mod(i32, 10, 12) == 10);
52 try expect(mod(i32, -14, 12) == 10);
53 try expect(mod(i32, -2, 12) == 10);
54
55 comptime {
56 try expect(
57 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
58 );
59 try expect(
60 @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
61 );
62 try expect(
63 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
64 );
65 try expect(
66 @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
67 );
68 try expect(
69 @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
70 );
71 try expect(
72 @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
73 );
74 try expect(
75 4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
76 );
77 }
78}
79fn div(comptime T: type, a: T, b: T) T {
80 return a / b;
81}
82fn divExact(comptime T: type, a: T, b: T) T {
83 return @divExact(a, b);
84}
85fn divFloor(comptime T: type, a: T, b: T) T {
86 return @divFloor(a, b);
87}
88fn divTrunc(comptime T: type, a: T, b: T) T {
89 return @divTrunc(a, b);
90}
91fn mod(comptime T: type, a: T, b: T) T {
92 return @mod(a, b);
93}
94
95test "@addWithOverflow" {
96 var result: u8 = undefined;
97 try expect(@addWithOverflow(u8, 250, 100, &result));
98 try expect(!@addWithOverflow(u8, 100, 150, &result));
99 try expect(result == 250);
100}
101
102// TODO test mulWithOverflow
103// TODO test subWithOverflow
104
105test "@shlWithOverflow" {
106 var result: u16 = undefined;
107 try expect(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
108 try expect(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
109 try expect(result == 0b1011111111111100);
110}
111
112test "@*WithOverflow with u0 values" {
113 var result: u0 = undefined;
114 try expect(!@addWithOverflow(u0, 0, 0, &result));
115 try expect(!@subWithOverflow(u0, 0, 0, &result));
116 try expect(!@mulWithOverflow(u0, 0, 0, &result));
117 try expect(!@shlWithOverflow(u0, 0, 0, &result));
118}
119
120test "@clz" {
121 try testClz();
122 comptime try testClz();
123}
124
125fn testClz() !void {
126 try expect(clz(u8, 0b10001010) == 0);
127 try expect(clz(u8, 0b00001010) == 4);
128 try expect(clz(u8, 0b00011010) == 3);
129 try expect(clz(u8, 0b00000000) == 8);
130 try expect(clz(u128, 0xffffffffffffffff) == 64);
131 try expect(clz(u128, 0x10000000000000000) == 63);
132}
133
134fn clz(comptime T: type, x: T) usize {
135 return @clz(T, x);
136}
137
138test "@ctz" {
139 try testCtz();
140 comptime try testCtz();
141}
142
143fn testCtz() !void {
144 try expect(ctz(u8, 0b10100000) == 5);
145 try expect(ctz(u8, 0b10001010) == 1);
146 try expect(ctz(u8, 0b00000000) == 8);
147 try expect(ctz(u16, 0b00000000) == 16);
148}
149
150fn ctz(comptime T: type, x: T) usize {
151 return @ctz(T, x);
152}
153
154test "assignment operators" {
155 var i: u32 = 0;
156 i += 5;
157 try expect(i == 5);
158 i -= 2;
159 try expect(i == 3);
160 i *= 20;
161 try expect(i == 60);
162 i /= 3;
163 try expect(i == 20);
164 i %= 11;
165 try expect(i == 9);
166 i <<= 1;
167 try expect(i == 18);
168 i >>= 2;
169 try expect(i == 4);
170 i = 6;
171 i &= 5;
172 try expect(i == 4);
173 i ^= 6;
174 try expect(i == 2);
175 i = 6;
176 i |= 3;
177 try expect(i == 7);
178}
179
180test "three expr in a row" {
181 try testThreeExprInARow(false, true);
182 comptime try testThreeExprInARow(false, true);
183}
184fn testThreeExprInARow(f: bool, t: bool) !void {
185 try assertFalse(f or f or f);
186 try assertFalse(t and t and f);
187 try assertFalse(1 | 2 | 4 != 7);
188 try assertFalse(3 ^ 6 ^ 8 != 13);
189 try assertFalse(7 & 14 & 28 != 4);
190 try assertFalse(9 << 1 << 2 != 9 << 3);
191 try assertFalse(90 >> 1 >> 2 != 90 >> 3);
192 try assertFalse(100 - 1 + 1000 != 1099);
193 try assertFalse(5 * 4 / 2 % 3 != 1);
194 try assertFalse(@as(i32, @as(i32, 5)) != 5);
195 try assertFalse(!!false);
196 try assertFalse(@as(i32, 7) != --(@as(i32, 7)));
197}
198fn assertFalse(b: bool) !void {
199 try expect(!b);
200}
201
202test "const number literal" {
203 const one = 1;
204 const eleven = ten + one;
205
206 try expect(eleven == 11);
207}
208const ten = 10;
209
210test "unsigned wrapping" {
211 try testUnsignedWrappingEval(maxInt(u32));
212 comptime try testUnsignedWrappingEval(maxInt(u32));
213}
214fn testUnsignedWrappingEval(x: u32) !void {
215 const zero = x +% 1;
216 try expect(zero == 0);
217 const orig = zero -% 1;
218 try expect(orig == maxInt(u32));
219}
220
221test "signed wrapping" {
222 try testSignedWrappingEval(maxInt(i32));
223 comptime try testSignedWrappingEval(maxInt(i32));
224}
225fn testSignedWrappingEval(x: i32) !void {
226 const min_val = x +% 1;
227 try expect(min_val == minInt(i32));
228 const max_val = min_val -% 1;
229 try expect(max_val == maxInt(i32));
230}
231
232test "signed negation wrapping" {
233 try testSignedNegationWrappingEval(minInt(i16));
234 comptime try testSignedNegationWrappingEval(minInt(i16));
235}
236fn testSignedNegationWrappingEval(x: i16) !void {
237 try expect(x == -32768);
238 const neg = -%x;
239 try expect(neg == -32768);
240}
241
242test "unsigned negation wrapping" {
243 try testUnsignedNegationWrappingEval(1);
244 comptime try testUnsignedNegationWrappingEval(1);
245}
246fn testUnsignedNegationWrappingEval(x: u16) !void {
247 try expect(x == 1);
248 const neg = -%x;
249 try expect(neg == maxInt(u16));
250}
251
252test "unsigned 64-bit division" {
253 try test_u64_div();
254 comptime try test_u64_div();
255}
256fn test_u64_div() !void {
257 const result = divWithResult(1152921504606846976, 34359738365);
258 try expect(result.quotient == 33554432);
259 try expect(result.remainder == 100663296);
260}
261fn divWithResult(a: u64, b: u64) DivResult {
262 return DivResult{
263 .quotient = a / b,
264 .remainder = a % b,
265 };
266}
267const DivResult = struct {
268 quotient: u64,
269 remainder: u64,
270};
271
272test "binary not" {
273 try expect(comptime x: {
274 break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101;
275 });
276 try expect(comptime x: {
277 break :x ~@as(u64, 2147483647) == 18446744071562067968;
278 });
279 try testBinaryNot(0b1010101010101010);
280}
281
282fn testBinaryNot(x: u16) !void {
283 try expect(~x == 0b0101010101010101);
284}
285
286test "small int addition" {
287 var x: u2 = 0;
288 try expect(x == 0);
289
290 x += 1;
291 try expect(x == 1);
292
293 x += 1;
294 try expect(x == 2);
295
296 x += 1;
297 try expect(x == 3);
298
299 var result: @TypeOf(x) = 3;
300 try expect(@addWithOverflow(@TypeOf(x), x, 1, &result));
301
302 try expect(result == 0);
303}
304
305test "float equality" {
306 const x: f64 = 0.012;
307 const y: f64 = x + 1.0;
308
309 try testFloatEqualityImpl(x, y);
310 comptime try testFloatEqualityImpl(x, y);
311}
312
313fn testFloatEqualityImpl(x: f64, y: f64) !void {
314 const y2 = x + 1.0;
315 try expect(y == y2);
316}
317
318test "allow signed integer division/remainder when values are comptime known and positive or exact" {
319 try expect(5 / 3 == 1);
320 try expect(-5 / -3 == 1);
321 try expect(-6 / 3 == -2);
322
323 try expect(5 % 3 == 2);
324 try expect(-6 % 3 == 0);
325}
326
327test "hex float literal parsing" {
328 comptime try expect(0x1.0 == 1.0);
329}
330
331test "quad hex float literal parsing in range" {
332 const a = 0x1.af23456789bbaaab347645365cdep+5;
333 const b = 0x1.dedafcff354b6ae9758763545432p-9;
334 const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534;
335 const d = 0x1.edcbff8ad76ab5bf46463233214fp-435;
336}
337
338test "quad hex float literal parsing accurate" {
339 const a: f128 = 0x1.1111222233334444555566667777p+0;
340
341 // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
342 const expected: u128 = 0x3fff1111222233334444555566667777;
343 try expect(@bitCast(u128, a) == expected);
344
345 // non-normalized
346 const b: f128 = 0x11.111222233334444555566667777p-4;
347 try expect(@bitCast(u128, b) == expected);
348
349 const S = struct {
350 fn doTheTest() !void {
351 {
352 var f: f128 = 0x1.2eab345678439abcdefea56782346p+5;
353 try expect(@bitCast(u128, f) == 0x40042eab345678439abcdefea5678234);
354 }
355 {
356 var f: f128 = 0x1.edcb34a235253948765432134674fp-1;
357 try expect(@bitCast(u128, f) == 0x3ffeedcb34a235253948765432134674);
358 }
359 {
360 var f: f128 = 0x1.353e45674d89abacc3a2ebf3ff4ffp-50;
361 try expect(@bitCast(u128, f) == 0x3fcd353e45674d89abacc3a2ebf3ff50);
362 }
363 {
364 var f: f128 = 0x1.ed8764648369535adf4be3214567fp-9;
365 try expect(@bitCast(u128, f) == 0x3ff6ed8764648369535adf4be3214568);
366 }
367 const exp2ft = [_]f64{
368 0x1.6a09e667f3bcdp-1,
369 0x1.7a11473eb0187p-1,
370 0x1.8ace5422aa0dbp-1,
371 0x1.9c49182a3f090p-1,
372 0x1.ae89f995ad3adp-1,
373 0x1.c199bdd85529cp-1,
374 0x1.d5818dcfba487p-1,
375 0x1.ea4afa2a490dap-1,
376 0x1.0000000000000p+0,
377 0x1.0b5586cf9890fp+0,
378 0x1.172b83c7d517bp+0,
379 0x1.2387a6e756238p+0,
380 0x1.306fe0a31b715p+0,
381 0x1.3dea64c123422p+0,
382 0x1.4bfdad5362a27p+0,
383 0x1.5ab07dd485429p+0,
384 0x1.8p23,
385 0x1.62e430p-1,
386 0x1.ebfbe0p-3,
387 0x1.c6b348p-5,
388 0x1.3b2c9cp-7,
389 0x1.0p127,
390 -0x1.0p-149,
391 };
392
393 const answers = [_]u64{
394 0x3fe6a09e667f3bcd,
395 0x3fe7a11473eb0187,
396 0x3fe8ace5422aa0db,
397 0x3fe9c49182a3f090,
398 0x3feae89f995ad3ad,
399 0x3fec199bdd85529c,
400 0x3fed5818dcfba487,
401 0x3feea4afa2a490da,
402 0x3ff0000000000000,
403 0x3ff0b5586cf9890f,
404 0x3ff172b83c7d517b,
405 0x3ff2387a6e756238,
406 0x3ff306fe0a31b715,
407 0x3ff3dea64c123422,
408 0x3ff4bfdad5362a27,
409 0x3ff5ab07dd485429,
410 0x4168000000000000,
411 0x3fe62e4300000000,
412 0x3fcebfbe00000000,
413 0x3fac6b3480000000,
414 0x3f83b2c9c0000000,
415 0x47e0000000000000,
416 0xb6a0000000000000,
417 };
418
419 for (exp2ft) |x, i| {
420 try expect(@bitCast(u64, x) == answers[i]);
421 }
422 }
423 };
424 try S.doTheTest();
425 comptime try S.doTheTest();
426}
427
428test "underscore separator parsing" {
429 try expect(0_0_0_0 == 0);
430 try expect(1_234_567 == 1234567);
431 try expect(001_234_567 == 1234567);
432 try expect(0_0_1_2_3_4_5_6_7 == 1234567);
433
434 try expect(0b0_0_0_0 == 0);
435 try expect(0b1010_1010 == 0b10101010);
436 try expect(0b0000_1010_1010 == 0b10101010);
437 try expect(0b1_0_1_0_1_0_1_0 == 0b10101010);
438
439 try expect(0o0_0_0_0 == 0);
440 try expect(0o1010_1010 == 0o10101010);
441 try expect(0o0000_1010_1010 == 0o10101010);
442 try expect(0o1_0_1_0_1_0_1_0 == 0o10101010);
443
444 try expect(0x0_0_0_0 == 0);
445 try expect(0x1010_1010 == 0x10101010);
446 try expect(0x0000_1010_1010 == 0x10101010);
447 try expect(0x1_0_1_0_1_0_1_0 == 0x10101010);
448
449 try expect(123_456.789_000e1_0 == 123456.789000e10);
450 try expect(0_1_2_3_4_5_6.7_8_9_0_0_0e0_0_1_0 == 123456.789000e10);
451
452 try expect(0x1234_5678.9ABC_DEF0p-1_0 == 0x12345678.9ABCDEF0p-10);
453 try expect(0x1_2_3_4_5_6_7_8.9_A_B_C_D_E_F_0p-0_0_0_1_0 == 0x12345678.9ABCDEF0p-10);
454}
455
456test "hex float literal within range" {
457 const a = 0x1.0p16383;
458 const b = 0x0.1p16387;
459 const c = 0x1.0p-16382;
460}
461
462test "truncating shift left" {
463 try testShlTrunc(maxInt(u16));
464 comptime try testShlTrunc(maxInt(u16));
465}
466fn testShlTrunc(x: u16) !void {
467 const shifted = x << 1;
468 try expect(shifted == 65534);
469}
470
471test "truncating shift right" {
472 try testShrTrunc(maxInt(u16));
473 comptime try testShrTrunc(maxInt(u16));
474}
475fn testShrTrunc(x: u16) !void {
476 const shifted = x >> 1;
477 try expect(shifted == 32767);
478}
479
480test "exact shift left" {
481 try testShlExact(0b00110101);
482 comptime try testShlExact(0b00110101);
483}
484fn testShlExact(x: u8) !void {
485 const shifted = @shlExact(x, 2);
486 try expect(shifted == 0b11010100);
487}
488
489test "exact shift right" {
490 try testShrExact(0b10110100);
491 comptime try testShrExact(0b10110100);
492}
493fn testShrExact(x: u8) !void {
494 const shifted = @shrExact(x, 2);
495 try expect(shifted == 0b00101101);
496}
497
498test "shift left/right on u0 operand" {
499 const S = struct {
500 fn doTheTest() !void {
501 var x: u0 = 0;
502 var y: u0 = 0;
503 try expectEqual(@as(u0, 0), x << 0);
504 try expectEqual(@as(u0, 0), x >> 0);
505 try expectEqual(@as(u0, 0), x << y);
506 try expectEqual(@as(u0, 0), x >> y);
507 try expectEqual(@as(u0, 0), @shlExact(x, 0));
508 try expectEqual(@as(u0, 0), @shrExact(x, 0));
509 try expectEqual(@as(u0, 0), @shlExact(x, y));
510 try expectEqual(@as(u0, 0), @shrExact(x, y));
511 }
512 };
513 try S.doTheTest();
514 comptime try S.doTheTest();
515}
516
517test "comptime_int addition" {
518 comptime {
519 try expect(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
520 try expect(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
521 }
522}
523
524test "comptime_int multiplication" {
525 comptime {
526 try expect(
527 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
528 );
529 try expect(
530 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
531 );
532 }
533}
534
535test "comptime_int shifting" {
536 comptime {
537 try expect((@as(u128, 1) << 127) == 0x80000000000000000000000000000000);
538 }
539}
540
541test "comptime_int multi-limb shift and mask" {
542 comptime {
543 var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
544
545 try expect(@as(u32, a & 0xffffffff) == 0xaaaaaaab);
546 a >>= 32;
547 try expect(@as(u32, a & 0xffffffff) == 0xeeeeeeef);
548 a >>= 32;
549 try expect(@as(u32, a & 0xffffffff) == 0xa0000001);
550 a >>= 32;
551 try expect(@as(u32, a & 0xffffffff) == 0xefffffff);
552 a >>= 32;
553
554 try expect(a == 0);
555 }
556}
557
558test "comptime_int multi-limb partial shift right" {
559 comptime {
560 var a = 0x1ffffffffeeeeeeee;
561 a >>= 16;
562 try expect(a == 0x1ffffffffeeee);
563 }
564}
565
566test "xor" {
567 try test_xor();
568 comptime try test_xor();
569}
570
571fn test_xor() !void {
572 try expect(0xFF ^ 0x00 == 0xFF);
573 try expect(0xF0 ^ 0x0F == 0xFF);
574 try expect(0xFF ^ 0xF0 == 0x0F);
575 try expect(0xFF ^ 0x0F == 0xF0);
576 try expect(0xFF ^ 0xFF == 0x00);
577}
578
579test "comptime_int xor" {
580 comptime {
581 try expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
582 try expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
583 try expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
584 try expect(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
585 try expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
586 try expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
587 try expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
588 try expect(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
589 }
590}
591
592test "f128" {
593 try test_f128();
594 comptime try test_f128();
595}
596
597fn make_f128(x: f128) f128 {
598 return x;
599}
600
601fn test_f128() !void {
602 try expect(@sizeOf(f128) == 16);
603 try expect(make_f128(1.0) == 1.0);
604 try expect(make_f128(1.0) != 1.1);
605 try expect(make_f128(1.0) > 0.9);
606 try expect(make_f128(1.0) >= 0.9);
607 try expect(make_f128(1.0) >= 1.0);
608 try should_not_be_zero(1.0);
609}
610
611fn should_not_be_zero(x: f128) !void {
612 try expect(x != 0.0);
613}
614
615test "comptime float rem int" {
616 comptime {
617 var x = @as(f32, 1) % 2;
618 try expect(x == 1.0);
619 }
620}
621
622test "remainder division" {
623 comptime try remdiv(f16);
624 comptime try remdiv(f32);
625 comptime try remdiv(f64);
626 comptime try remdiv(f128);
627 try remdiv(f16);
628 try remdiv(f64);
629 try remdiv(f128);
630}
631
632fn remdiv(comptime T: type) !void {
633 try expect(@as(T, 1) == @as(T, 1) % @as(T, 2));
634 try expect(@as(T, 1) == @as(T, 7) % @as(T, 3));
635}
636
637test "@sqrt" {
638 try testSqrt(f64, 12.0);
639 comptime try testSqrt(f64, 12.0);
640 try testSqrt(f32, 13.0);
641 comptime try testSqrt(f32, 13.0);
642 try testSqrt(f16, 13.0);
643 comptime try testSqrt(f16, 13.0);
644
645 const x = 14.0;
646 const y = x * x;
647 const z = @sqrt(y);
648 comptime try expect(z == x);
649}
650
651fn testSqrt(comptime T: type, x: T) !void {
652 try expect(@sqrt(x * x) == x);
653}
654
655test "@fabs" {
656 try testFabs(f128, 12.0);
657 comptime try testFabs(f128, 12.0);
658 try testFabs(f64, 12.0);
659 comptime try testFabs(f64, 12.0);
660 try testFabs(f32, 12.0);
661 comptime try testFabs(f32, 12.0);
662 try testFabs(f16, 12.0);
663 comptime try testFabs(f16, 12.0);
664
665 const x = 14.0;
666 const y = -x;
667 const z = @fabs(y);
668 comptime try expectEqual(x, z);
669}
670
671fn testFabs(comptime T: type, x: T) !void {
672 const y = -x;
673 const z = @fabs(y);
674 try expectEqual(x, z);
675}
676
677test "@floor" {
678 // FIXME: Generates a floorl function call
679 // testFloor(f128, 12.0);
680 comptime try testFloor(f128, 12.0);
681 try testFloor(f64, 12.0);
682 comptime try testFloor(f64, 12.0);
683 try testFloor(f32, 12.0);
684 comptime try testFloor(f32, 12.0);
685 try testFloor(f16, 12.0);
686 comptime try testFloor(f16, 12.0);
687
688 const x = 14.0;
689 const y = x + 0.7;
690 const z = @floor(y);
691 comptime try expectEqual(x, z);
692}
693
694fn testFloor(comptime T: type, x: T) !void {
695 const y = x + 0.6;
696 const z = @floor(y);
697 try expectEqual(x, z);
698}
699
700test "@ceil" {
701 // FIXME: Generates a ceill function call
702 //testCeil(f128, 12.0);
703 comptime try testCeil(f128, 12.0);
704 try testCeil(f64, 12.0);
705 comptime try testCeil(f64, 12.0);
706 try testCeil(f32, 12.0);
707 comptime try testCeil(f32, 12.0);
708 try testCeil(f16, 12.0);
709 comptime try testCeil(f16, 12.0);
710
711 const x = 14.0;
712 const y = x - 0.7;
713 const z = @ceil(y);
714 comptime try expectEqual(x, z);
715}
716
717fn testCeil(comptime T: type, x: T) !void {
718 const y = x - 0.8;
719 const z = @ceil(y);
720 try expectEqual(x, z);
721}
722
723test "@trunc" {
724 // FIXME: Generates a truncl function call
725 //testTrunc(f128, 12.0);
726 comptime try testTrunc(f128, 12.0);
727 try testTrunc(f64, 12.0);
728 comptime try testTrunc(f64, 12.0);
729 try testTrunc(f32, 12.0);
730 comptime try testTrunc(f32, 12.0);
731 try testTrunc(f16, 12.0);
732 comptime try testTrunc(f16, 12.0);
733
734 const x = 14.0;
735 const y = x + 0.7;
736 const z = @trunc(y);
737 comptime try expectEqual(x, z);
738}
739
740fn testTrunc(comptime T: type, x: T) !void {
741 {
742 const y = x + 0.8;
743 const z = @trunc(y);
744 try expectEqual(x, z);
745 }
746
747 {
748 const y = -x - 0.8;
749 const z = @trunc(y);
750 try expectEqual(-x, z);
751 }
752}
753
754test "@round" {
755 // FIXME: Generates a roundl function call
756 //testRound(f128, 12.0);
757 comptime try testRound(f128, 12.0);
758 try testRound(f64, 12.0);
759 comptime try testRound(f64, 12.0);
760 try testRound(f32, 12.0);
761 comptime try testRound(f32, 12.0);
762 try testRound(f16, 12.0);
763 comptime try testRound(f16, 12.0);
764
765 const x = 14.0;
766 const y = x + 0.4;
767 const z = @round(y);
768 comptime try expectEqual(x, z);
769}
770
771fn testRound(comptime T: type, x: T) !void {
772 const y = x - 0.5;
773 const z = @round(y);
774 try expectEqual(x, z);
775}
776
777test "comptime_int param and return" {
778 const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
779 try expect(a == 137114567242441932203689521744947848950);
780
781 const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
782 try expect(b == 985095453608931032642182098849559179469148836107390954364380);
783}
784
785fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
786 return a + b;
787}
788
789test "vector integer addition" {
790 const S = struct {
791 fn doTheTest() !void {
792 var a: std.meta.Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };
793 var b: std.meta.Vector(4, i32) = [_]i32{ 5, 6, 7, 8 };
794 var result = a + b;
795 var result_array: [4]i32 = result;
796 const expected = [_]i32{ 6, 8, 10, 12 };
797 try expectEqualSlices(i32, &expected, &result_array);
798 }
799 };
800 try S.doTheTest();
801 comptime try S.doTheTest();
802}
803
804test "NaN comparison" {
805 try testNanEqNan(f16);
806 try testNanEqNan(f32);
807 try testNanEqNan(f64);
808 try testNanEqNan(f128);
809 comptime try testNanEqNan(f16);
810 comptime try testNanEqNan(f32);
811 comptime try testNanEqNan(f64);
812 comptime try testNanEqNan(f128);
813}
814
815fn testNanEqNan(comptime F: type) !void {
816 var nan1 = std.math.nan(F);
817 var nan2 = std.math.nan(F);
818 try expect(nan1 != nan2);
819 try expect(!(nan1 == nan2));
820 try expect(!(nan1 > nan2));
821 try expect(!(nan1 >= nan2));
822 try expect(!(nan1 < nan2));
823 try expect(!(nan1 <= nan2));
824}
825
826test "128-bit multiplication" {
827 var a: i128 = 3;
828 var b: i128 = 2;
829 var c = a * b;
830 try expect(c == 6);
831}
832
833test "vector comparison" {
834 const S = struct {
835 fn doTheTest() !void {
836 var a: std.meta.Vector(6, i32) = [_]i32{ 1, 3, -1, 5, 7, 9 };
837 var b: std.meta.Vector(6, i32) = [_]i32{ -1, 3, 0, 6, 10, -10 };
838 try expect(mem.eql(bool, &@as([6]bool, a < b), &[_]bool{ false, false, true, true, true, false }));
839 try expect(mem.eql(bool, &@as([6]bool, a <= b), &[_]bool{ false, true, true, true, true, false }));
840 try expect(mem.eql(bool, &@as([6]bool, a == b), &[_]bool{ false, true, false, false, false, false }));
841 try expect(mem.eql(bool, &@as([6]bool, a != b), &[_]bool{ true, false, true, true, true, true }));
842 try expect(mem.eql(bool, &@as([6]bool, a > b), &[_]bool{ true, false, false, false, false, true }));
843 try expect(mem.eql(bool, &@as([6]bool, a >= b), &[_]bool{ true, true, false, false, false, true }));
844 }
845 };
846 try S.doTheTest();
847 comptime try S.doTheTest();
848}
849
850test "compare undefined literal with comptime_int" {
851 var x = undefined == 1;
852 // x is now undefined with type bool
853 x = true;
854 try expect(x);
855}
856
857test "signed zeros are represented properly" {
858 const S = struct {
859 fn doTheTest() !void {
860 inline for ([_]type{ f16, f32, f64, f128 }) |T| {
861 const ST = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
862 var as_fp_val = -@as(T, 0.0);
863 var as_uint_val = @bitCast(ST, as_fp_val);
864 // Ensure the sign bit is set.
865 try expect(as_uint_val >> (@typeInfo(T).Float.bits - 1) == 1);
866 }
867 }
868 };
869
870 try S.doTheTest();
871 comptime try S.doTheTest();
872}
test/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/behavior/misc.zig created+761
...@@ -0,0 +1,761 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
4const mem = std.mem;
5const builtin = @import("builtin");
6
7// normal comment
8
9/// this is a documentation comment
10/// doc comment line 2
11fn emptyFunctionWithComments() void {}
12
13test "empty function with comments" {
14 emptyFunctionWithComments();
15}
16
17comptime {
18 @export(disabledExternFn, .{ .name = "disabledExternFn", .linkage = .Internal });
19}
20
21fn disabledExternFn() callconv(.C) void {}
22
23test "call disabled extern fn" {
24 disabledExternFn();
25}
26
27test "short circuit" {
28 try testShortCircuit(false, true);
29 comptime try testShortCircuit(false, true);
30}
31
32fn testShortCircuit(f: bool, t: bool) !void {
33 var hit_1 = f;
34 var hit_2 = f;
35 var hit_3 = f;
36 var hit_4 = f;
37
38 if (t or x: {
39 try expect(f);
40 break :x f;
41 }) {
42 hit_1 = t;
43 }
44 if (f or x: {
45 hit_2 = t;
46 break :x f;
47 }) {
48 try expect(f);
49 }
50
51 if (t and x: {
52 hit_3 = t;
53 break :x f;
54 }) {
55 try expect(f);
56 }
57 if (f and x: {
58 try expect(f);
59 break :x f;
60 }) {
61 try expect(f);
62 } else {
63 hit_4 = t;
64 }
65 try expect(hit_1);
66 try expect(hit_2);
67 try expect(hit_3);
68 try expect(hit_4);
69}
70
71test "truncate" {
72 try expect(testTruncate(0x10fd) == 0xfd);
73}
74fn testTruncate(x: u32) u8 {
75 return @truncate(u8, x);
76}
77
78fn first4KeysOfHomeRow() []const u8 {
79 return "aoeu";
80}
81
82test "return string from function" {
83 try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
84}
85
86const g1: i32 = 1233 + 1;
87var g2: i32 = 0;
88
89test "global variables" {
90 try expect(g2 == 0);
91 g2 = g1;
92 try expect(g2 == 1234);
93}
94
95test "memcpy and memset intrinsics" {
96 var foo: [20]u8 = undefined;
97 var bar: [20]u8 = undefined;
98
99 @memset(&foo, 'A', foo.len);
100 @memcpy(&bar, &foo, bar.len);
101
102 if (bar[11] != 'A') unreachable;
103}
104
105test "builtin static eval" {
106 const x: i32 = comptime x: {
107 break :x 1 + 2 + 3;
108 };
109 try expect(x == comptime 6);
110}
111
112test "slicing" {
113 var array: [20]i32 = undefined;
114
115 array[5] = 1234;
116
117 var slice = array[5..10];
118
119 if (slice.len != 5) unreachable;
120
121 const ptr = &slice[0];
122 if (ptr.* != 1234) unreachable;
123
124 var slice_rest = array[10..];
125 if (slice_rest.len != 10) unreachable;
126}
127
128test "constant equal function pointers" {
129 const alias = emptyFn;
130 try expect(comptime x: {
131 break :x emptyFn == alias;
132 });
133}
134
135fn emptyFn() void {}
136
137test "hex escape" {
138 try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
139}
140
141test "string concatenation" {
142 try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
143}
144
145test "array mult operator" {
146 try expect(mem.eql(u8, "ab" ** 5, "ababababab"));
147}
148
149test "string escapes" {
150 try expect(mem.eql(u8, "\"", "\x22"));
151 try expect(mem.eql(u8, "\'", "\x27"));
152 try expect(mem.eql(u8, "\n", "\x0a"));
153 try expect(mem.eql(u8, "\r", "\x0d"));
154 try expect(mem.eql(u8, "\t", "\x09"));
155 try expect(mem.eql(u8, "\\", "\x5c"));
156 try expect(mem.eql(u8, "\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01"));
157}
158
159test "multiline string" {
160 const s1 =
161 \\one
162 \\two)
163 \\three
164 ;
165 const s2 = "one\ntwo)\nthree";
166 try expect(mem.eql(u8, s1, s2));
167}
168
169test "multiline string comments at start" {
170 const s1 =
171 //\\one
172 \\two)
173 \\three
174 ;
175 const s2 = "two)\nthree";
176 try expect(mem.eql(u8, s1, s2));
177}
178
179test "multiline string comments at end" {
180 const s1 =
181 \\one
182 \\two)
183 //\\three
184 ;
185 const s2 = "one\ntwo)";
186 try expect(mem.eql(u8, s1, s2));
187}
188
189test "multiline string comments in middle" {
190 const s1 =
191 \\one
192 //\\two)
193 \\three
194 ;
195 const s2 = "one\nthree";
196 try expect(mem.eql(u8, s1, s2));
197}
198
199test "multiline string comments at multiple places" {
200 const s1 =
201 \\one
202 //\\two
203 \\three
204 //\\four
205 \\five
206 ;
207 const s2 = "one\nthree\nfive";
208 try expect(mem.eql(u8, s1, s2));
209}
210
211test "multiline C string" {
212 const s1 =
213 \\one
214 \\two)
215 \\three
216 ;
217 const s2 = "one\ntwo)\nthree";
218 try expect(std.cstr.cmp(s1, s2) == 0);
219}
220
221test "type equality" {
222 try expect(*const u8 != *u8);
223}
224
225const global_a: i32 = 1234;
226const global_b: *const i32 = &global_a;
227const global_c: *const f32 = @ptrCast(*const f32, global_b);
228test "compile time global reinterpret" {
229 const d = @ptrCast(*const i32, global_c);
230 try expect(d.* == 1234);
231}
232
233test "explicit cast maybe pointers" {
234 const a: ?*i32 = undefined;
235 const b: ?*f32 = @ptrCast(?*f32, a);
236}
237
238test "generic malloc free" {
239 const a = memAlloc(u8, 10) catch unreachable;
240 memFree(u8, a);
241}
242var some_mem: [100]u8 = undefined;
243fn memAlloc(comptime T: type, n: usize) anyerror![]T {
244 return @ptrCast([*]T, &some_mem[0])[0..n];
245}
246fn memFree(comptime T: type, memory: []T) void {}
247
248test "cast undefined" {
249 const array: [100]u8 = undefined;
250 const slice = @as([]const u8, &array);
251 testCastUndefined(slice);
252}
253fn testCastUndefined(x: []const u8) void {}
254
255test "cast small unsigned to larger signed" {
256 try expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200));
257 try expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999));
258}
259fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
260 return x;
261}
262fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
263 return x;
264}
265
266test "implicit cast after unreachable" {
267 try expect(outer() == 1234);
268}
269fn inner() i32 {
270 return 1234;
271}
272fn outer() i64 {
273 return inner();
274}
275
276test "pointer dereferencing" {
277 var x = @as(i32, 3);
278 const y = &x;
279
280 y.* += 1;
281
282 try expect(x == 4);
283 try expect(y.* == 4);
284}
285
286test "call result of if else expression" {
287 try expect(mem.eql(u8, f2(true), "a"));
288 try expect(mem.eql(u8, f2(false), "b"));
289}
290fn f2(x: bool) []const u8 {
291 return (if (x) fA else fB)();
292}
293fn fA() []const u8 {
294 return "a";
295}
296fn fB() []const u8 {
297 return "b";
298}
299
300test "const expression eval handling of variables" {
301 var x = true;
302 while (x) {
303 x = false;
304 }
305}
306
307test "constant enum initialization with differing sizes" {
308 try test3_1(test3_foo);
309 try test3_2(test3_bar);
310}
311const Test3Foo = union(enum) {
312 One: void,
313 Two: f32,
314 Three: Test3Point,
315};
316const Test3Point = struct {
317 x: i32,
318 y: i32,
319};
320const test3_foo = Test3Foo{
321 .Three = Test3Point{
322 .x = 3,
323 .y = 4,
324 },
325};
326const test3_bar = Test3Foo{ .Two = 13 };
327fn test3_1(f: Test3Foo) !void {
328 switch (f) {
329 Test3Foo.Three => |pt| {
330 try expect(pt.x == 3);
331 try expect(pt.y == 4);
332 },
333 else => unreachable,
334 }
335}
336fn test3_2(f: Test3Foo) !void {
337 switch (f) {
338 Test3Foo.Two => |x| {
339 try expect(x == 13);
340 },
341 else => unreachable,
342 }
343}
344
345test "character literals" {
346 try expect('\'' == single_quote);
347}
348const single_quote = '\'';
349
350test "take address of parameter" {
351 try testTakeAddressOfParameter(12.34);
352}
353fn testTakeAddressOfParameter(f: f32) !void {
354 const f_ptr = &f;
355 try expect(f_ptr.* == 12.34);
356}
357
358test "pointer comparison" {
359 const a = @as([]const u8, "a");
360 const b = &a;
361 try expect(ptrEql(b, b));
362}
363fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
364 return a == b;
365}
366
367test "string concatenation" {
368 const a = "OK" ++ " IT " ++ "WORKED";
369 const b = "OK IT WORKED";
370
371 comptime try expect(@TypeOf(a) == *const [12:0]u8);
372 comptime try expect(@TypeOf(b) == *const [12:0]u8);
373
374 const len = mem.len(b);
375 const len_with_null = len + 1;
376 {
377 var i: u32 = 0;
378 while (i < len_with_null) : (i += 1) {
379 try expect(a[i] == b[i]);
380 }
381 }
382 try expect(a[len] == 0);
383 try expect(b[len] == 0);
384}
385
386test "pointer to void return type" {
387 testPointerToVoidReturnType() catch unreachable;
388}
389fn testPointerToVoidReturnType() anyerror!void {
390 const a = testPointerToVoidReturnType2();
391 return a.*;
392}
393const test_pointer_to_void_return_type_x = void{};
394fn testPointerToVoidReturnType2() *const void {
395 return &test_pointer_to_void_return_type_x;
396}
397
398test "non const ptr to aliased type" {
399 const int = i32;
400 try expect(?*int == ?*i32);
401}
402
403test "array 2D const double ptr" {
404 const rect_2d_vertexes = [_][1]f32{
405 [_]f32{1.0},
406 [_]f32{2.0},
407 };
408 try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
409}
410
411fn testArray2DConstDoublePtr(ptr: *const f32) !void {
412 const ptr2 = @ptrCast([*]const f32, ptr);
413 try expect(ptr2[0] == 1.0);
414 try expect(ptr2[1] == 2.0);
415}
416
417const AStruct = struct {
418 x: i32,
419};
420const AnEnum = enum {
421 One,
422 Two,
423};
424const AUnionEnum = union(enum) {
425 One: i32,
426 Two: void,
427};
428const AUnion = union {
429 One: void,
430 Two: void,
431};
432
433test "@typeName" {
434 const Struct = struct {};
435 const Union = union {
436 unused: u8,
437 };
438 const Enum = enum {
439 Unused,
440 };
441 comptime {
442 try expect(mem.eql(u8, @typeName(i64), "i64"));
443 try expect(mem.eql(u8, @typeName(*usize), "*usize"));
444 // https://github.com/ziglang/zig/issues/675
445 try expect(mem.eql(u8, "behavior.misc.TypeFromFn(u8)", @typeName(TypeFromFn(u8))));
446 try expect(mem.eql(u8, @typeName(Struct), "Struct"));
447 try expect(mem.eql(u8, @typeName(Union), "Union"));
448 try expect(mem.eql(u8, @typeName(Enum), "Enum"));
449 }
450}
451
452fn TypeFromFn(comptime T: type) type {
453 return struct {};
454}
455
456test "double implicit cast in same expression" {
457 var x = @as(i32, @as(u16, nine()));
458 try expect(x == 9);
459}
460fn nine() u8 {
461 return 9;
462}
463
464test "global variable initialized to global variable array element" {
465 try expect(global_ptr == &gdt[0]);
466}
467const GDTEntry = struct {
468 field: i32,
469};
470var gdt = [_]GDTEntry{
471 GDTEntry{ .field = 1 },
472 GDTEntry{ .field = 2 },
473};
474var global_ptr = &gdt[0];
475
476// can't really run this test but we can make sure it has no compile error
477// and generates code
478const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
479export fn writeToVRam() void {
480 vram[0] = 'X';
481}
482
483const OpaqueA = opaque {};
484const OpaqueB = opaque {};
485test "opaque types" {
486 try expect(*OpaqueA != *OpaqueB);
487 try expect(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
488 try expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
489}
490
491test "variable is allowed to be a pointer to an opaque type" {
492 var x: i32 = 1234;
493 _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
494}
495fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
496 var a = ptr;
497 return a;
498}
499
500test "comptime if inside runtime while which unconditionally breaks" {
501 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
502 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
503}
504fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
505 while (cond) {
506 if (false) {}
507 break;
508 }
509}
510
511test "implicit comptime while" {
512 while (false) {
513 @compileError("bad");
514 }
515}
516
517fn fnThatClosesOverLocalConst() type {
518 const c = 1;
519 return struct {
520 fn g() i32 {
521 return c;
522 }
523 };
524}
525
526test "function closes over local const" {
527 const x = fnThatClosesOverLocalConst().g();
528 try expect(x == 1);
529}
530
531test "cold function" {
532 thisIsAColdFn();
533 comptime thisIsAColdFn();
534}
535
536fn thisIsAColdFn() void {
537 @setCold(true);
538}
539
540const PackedStruct = packed struct {
541 a: u8,
542 b: u8,
543};
544const PackedUnion = packed union {
545 a: u8,
546 b: u32,
547};
548const PackedEnum = packed enum {
549 A,
550 B,
551};
552
553test "packed struct, enum, union parameters in extern function" {
554 testPackedStuff(&(PackedStruct{
555 .a = 1,
556 .b = 2,
557 }), &(PackedUnion{ .a = 1 }), PackedEnum.A);
558}
559
560export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {}
561
562test "slicing zero length array" {
563 const s1 = ""[0..];
564 const s2 = ([_]u32{})[0..];
565 try expect(s1.len == 0);
566 try expect(s2.len == 0);
567 try expect(mem.eql(u8, s1, ""));
568 try expect(mem.eql(u32, s2, &[_]u32{}));
569}
570
571const addr1 = @ptrCast(*const u8, emptyFn);
572test "comptime cast fn to ptr" {
573 const addr2 = @ptrCast(*const u8, emptyFn);
574 comptime try expect(addr1 == addr2);
575}
576
577test "equality compare fn ptrs" {
578 var a = emptyFn;
579 try expect(a == a);
580}
581
582test "self reference through fn ptr field" {
583 const S = struct {
584 const A = struct {
585 f: fn (A) u8,
586 };
587
588 fn foo(a: A) u8 {
589 return 12;
590 }
591 };
592 var a: S.A = undefined;
593 a.f = S.foo;
594 try expect(a.f(a) == 12);
595}
596
597test "volatile load and store" {
598 var number: i32 = 1234;
599 const ptr = @as(*volatile i32, &number);
600 ptr.* += 1;
601 try expect(ptr.* == 1235);
602}
603
604test "slice string literal has correct type" {
605 comptime {
606 try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
607 const array = [_]i32{ 1, 2, 3, 4 };
608 try expect(@TypeOf(array[0..]) == *const [4]i32);
609 }
610 var runtime_zero: usize = 0;
611 comptime try expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);
612 const array = [_]i32{ 1, 2, 3, 4 };
613 comptime try expect(@TypeOf(array[runtime_zero..]) == []const i32);
614}
615
616test "struct inside function" {
617 try testStructInFn();
618 comptime try testStructInFn();
619}
620
621fn testStructInFn() !void {
622 const BlockKind = u32;
623
624 const Block = struct {
625 kind: BlockKind,
626 };
627
628 var block = Block{ .kind = 1234 };
629
630 block.kind += 1;
631
632 try expect(block.kind == 1235);
633}
634
635test "fn call returning scalar optional in equality expression" {
636 try expect(getNull() == null);
637}
638
639fn getNull() ?*i32 {
640 return null;
641}
642
643test "thread local variable" {
644 const S = struct {
645 threadlocal var t: i32 = 1234;
646 };
647 S.t += 1;
648 try expect(S.t == 1235);
649}
650
651test "unicode escape in character literal" {
652 var a: u24 = '\u{01f4a9}';
653 try expect(a == 128169);
654}
655
656test "unicode character in character literal" {
657 try expect('💩' == 128169);
658}
659
660test "result location zero sized array inside struct field implicit cast to slice" {
661 const E = struct {
662 entries: []u32,
663 };
664 var foo = E{ .entries = &[_]u32{} };
665 try expect(foo.entries.len == 0);
666}
667
668var global_foo: *i32 = undefined;
669
670test "global variable assignment with optional unwrapping with var initialized to undefined" {
671 const S = struct {
672 var data: i32 = 1234;
673 fn foo() ?*i32 {
674 return &data;
675 }
676 };
677 global_foo = S.foo() orelse {
678 @panic("bad");
679 };
680 try expect(global_foo.* == 1234);
681}
682
683test "peer result location with typed parent, runtime condition, comptime prongs" {
684 const S = struct {
685 fn doTheTest(arg: i32) i32 {
686 const st = Structy{
687 .bleh = if (arg == 1) 1 else 1,
688 };
689
690 if (st.bleh == 1)
691 return 1234;
692 return 0;
693 }
694
695 const Structy = struct {
696 bleh: i32,
697 };
698 };
699 try expect(S.doTheTest(0) == 1234);
700 try expect(S.doTheTest(1) == 1234);
701}
702
703test "nested optional field in struct" {
704 const S2 = struct {
705 y: u8,
706 };
707 const S1 = struct {
708 x: ?S2,
709 };
710 var s = S1{
711 .x = S2{ .y = 127 },
712 };
713 try expect(s.x.?.y == 127);
714}
715
716fn maybe(x: bool) anyerror!?u32 {
717 return switch (x) {
718 true => @as(u32, 42),
719 else => null,
720 };
721}
722
723test "result location is optional inside error union" {
724 const x = maybe(true) catch unreachable;
725 try expect(x.? == 42);
726}
727
728threadlocal var buffer: [11]u8 = undefined;
729
730test "pointer to thread local array" {
731 const s = "Hello world";
732 std.mem.copy(u8, buffer[0..], s);
733 try std.testing.expectEqualSlices(u8, buffer[0..], s);
734}
735
736test "auto created variables have correct alignment" {
737 const S = struct {
738 fn foo(str: [*]const u8) u32 {
739 for (@ptrCast([*]align(1) const u32, str)[0..1]) |v| {
740 return v;
741 }
742 return 0;
743 }
744 };
745 try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
746 comptime try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
747}
748
749extern var opaque_extern_var: opaque {};
750var var_to_export: u32 = 42;
751test "extern variable with non-pointer opaque type" {
752 @export(var_to_export, .{ .name = "opaque_extern_var" });
753 try expect(@ptrCast(*align(1) u32, &opaque_extern_var).* == 42);
754}
755
756test "lazy typeInfo value as generic parameter" {
757 const S = struct {
758 fn foo(args: anytype) void {}
759 };
760 S.foo(@typeInfo(@TypeOf(.{})));
761}
test/behavior/muladd.zig created+34
...@@ -0,0 +1,34 @@
1const expect = @import("std").testing.expect;
2
3test "@mulAdd" {
4 comptime try testMulAdd();
5 try testMulAdd();
6}
7
8fn testMulAdd() !void {
9 {
10 var a: f16 = 5.5;
11 var b: f16 = 2.5;
12 var c: f16 = 6.25;
13 try expect(@mulAdd(f16, a, b, c) == 20);
14 }
15 {
16 var a: f32 = 5.5;
17 var b: f32 = 2.5;
18 var c: f32 = 6.25;
19 try expect(@mulAdd(f32, a, b, c) == 20);
20 }
21 {
22 var a: f64 = 5.5;
23 var b: f64 = 2.5;
24 var c: f64 = 6.25;
25 try expect(@mulAdd(f64, a, b, c) == 20);
26 }
27 // Awaits implementation in libm.zig
28 //{
29 // var a: f16 = 5.5;
30 // var b: f128 = 2.5;
31 // var c: f128 = 6.25;
32 //try expect(@mulAdd(f128, a, b, c) == 20);
33 //}
34}
test/behavior/namespace_depends_on_compile_var.zig created+14
...@@ -0,0 +1,14 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "namespace depends on compile var" {
5 if (some_namespace.a_bool) {
6 try expect(some_namespace.a_bool);
7 } else {
8 try expect(!some_namespace.a_bool);
9 }
10}
11const some_namespace = switch (std.builtin.os.tag) {
12 .linux => @import("namespace_depends_on_compile_var/a.zig"),
13 else => @import("namespace_depends_on_compile_var/b.zig"),
14};
test/behavior/namespace_depends_on_compile_var/a.zig created+1
...@@ -0,0 +1 @@
1pub const a_bool = true;
test/behavior/namespace_depends_on_compile_var/b.zig created+1
...@@ -0,0 +1 @@
1pub const a_bool = false;
test/behavior/null.zig created+162
...@@ -0,0 +1,162 @@
1const expect = @import("std").testing.expect;
2
3test "optional type" {
4 const x: ?bool = true;
5
6 if (x) |y| {
7 if (y) {
8 // OK
9 } else {
10 unreachable;
11 }
12 } else {
13 unreachable;
14 }
15
16 const next_x: ?i32 = null;
17
18 const z = next_x orelse 1234;
19
20 try expect(z == 1234);
21
22 const final_x: ?i32 = 13;
23
24 const num = final_x orelse unreachable;
25
26 try expect(num == 13);
27}
28
29test "test maybe object and get a pointer to the inner value" {
30 var maybe_bool: ?bool = true;
31
32 if (maybe_bool) |*b| {
33 b.* = false;
34 }
35
36 try expect(maybe_bool.? == false);
37}
38
39test "rhs maybe unwrap return" {
40 const x: ?bool = true;
41 const y = x orelse return;
42}
43
44test "maybe return" {
45 try maybeReturnImpl();
46 comptime try maybeReturnImpl();
47}
48
49fn maybeReturnImpl() !void {
50 try expect(foo(1235).?);
51 if (foo(null) != null) unreachable;
52 try expect(!foo(1234).?);
53}
54
55fn foo(x: ?i32) ?bool {
56 const value = x orelse return null;
57 return value > 1234;
58}
59
60test "if var maybe pointer" {
61 try expect(shouldBeAPlus1(Particle{
62 .a = 14,
63 .b = 1,
64 .c = 1,
65 .d = 1,
66 }) == 15);
67}
68fn shouldBeAPlus1(p: Particle) u64 {
69 var maybe_particle: ?Particle = p;
70 if (maybe_particle) |*particle| {
71 particle.a += 1;
72 }
73 if (maybe_particle) |particle| {
74 return particle.a;
75 }
76 return 0;
77}
78const Particle = struct {
79 a: u64,
80 b: u64,
81 c: u64,
82 d: u64,
83};
84
85test "null literal outside function" {
86 const is_null = here_is_a_null_literal.context == null;
87 try expect(is_null);
88
89 const is_non_null = here_is_a_null_literal.context != null;
90 try expect(!is_non_null);
91}
92const SillyStruct = struct {
93 context: ?i32,
94};
95const here_is_a_null_literal = SillyStruct{ .context = null };
96
97test "test null runtime" {
98 try testTestNullRuntime(null);
99}
100fn testTestNullRuntime(x: ?i32) !void {
101 try expect(x == null);
102 try expect(!(x != null));
103}
104
105test "optional void" {
106 try optionalVoidImpl();
107 comptime try optionalVoidImpl();
108}
109
110fn optionalVoidImpl() !void {
111 try expect(bar(null) == null);
112 try expect(bar({}) != null);
113}
114
115fn bar(x: ?void) ?void {
116 if (x) |_| {
117 return {};
118 } else {
119 return null;
120 }
121}
122
123const StructWithOptional = struct {
124 field: ?i32,
125};
126
127var struct_with_optional: StructWithOptional = undefined;
128
129test "unwrap optional which is field of global var" {
130 struct_with_optional.field = null;
131 if (struct_with_optional.field) |payload| {
132 unreachable;
133 }
134 struct_with_optional.field = 1234;
135 if (struct_with_optional.field) |payload| {
136 try expect(payload == 1234);
137 } else {
138 unreachable;
139 }
140}
141
142test "null with default unwrap" {
143 const x: i32 = null orelse 1;
144 try expect(x == 1);
145}
146
147test "optional types" {
148 comptime {
149 const opt_type_struct = StructWithOptionalType{ .t = u8 };
150 try expect(opt_type_struct.t != null and opt_type_struct.t.? == u8);
151 }
152}
153
154const StructWithOptionalType = struct {
155 t: ?type,
156};
157
158test "optional pointer to 0 bit type null value at runtime" {
159 const EmptyStruct = struct {};
160 var x: ?*EmptyStruct = null;
161 try expect(x == null);
162}
test/behavior/optional.zig created+269
...@@ -0,0 +1,269 @@
1const std = @import("std");
2const testing = std.testing;
3const expect = testing.expect;
4const expectEqual = testing.expectEqual;
5
6pub const EmptyStruct = struct {};
7
8test "optional pointer to size zero struct" {
9 var e = EmptyStruct{};
10 var o: ?*EmptyStruct = &e;
11 try expect(o != null);
12}
13
14test "equality compare nullable pointers" {
15 try testNullPtrsEql();
16 comptime try testNullPtrsEql();
17}
18
19fn testNullPtrsEql() !void {
20 var number: i32 = 1234;
21
22 var x: ?*i32 = null;
23 var y: ?*i32 = null;
24 try expect(x == y);
25 y = &number;
26 try expect(x != y);
27 try expect(x != &number);
28 try expect(&number != x);
29 x = &number;
30 try expect(x == y);
31 try expect(x == &number);
32 try expect(&number == x);
33}
34
35test "address of unwrap optional" {
36 const S = struct {
37 const Foo = struct {
38 a: i32,
39 };
40
41 var global: ?Foo = null;
42
43 pub fn getFoo() anyerror!*Foo {
44 return &global.?;
45 }
46 };
47 S.global = S.Foo{ .a = 1234 };
48 const foo = S.getFoo() catch unreachable;
49 try expect(foo.a == 1234);
50}
51
52test "equality compare optional with non-optional" {
53 try test_cmp_optional_non_optional();
54 comptime try test_cmp_optional_non_optional();
55}
56
57fn test_cmp_optional_non_optional() !void {
58 var ten: i32 = 10;
59 var opt_ten: ?i32 = 10;
60 var five: i32 = 5;
61 var int_n: ?i32 = null;
62
63 try expect(int_n != ten);
64 try expect(opt_ten == ten);
65 try expect(opt_ten != five);
66
67 // test evaluation is always lexical
68 // ensure that the optional isn't always computed before the non-optional
69 var mutable_state: i32 = 0;
70 _ = blk1: {
71 mutable_state += 1;
72 break :blk1 @as(?f64, 10.0);
73 } != blk2: {
74 try expect(mutable_state == 1);
75 break :blk2 @as(f64, 5.0);
76 };
77 _ = blk1: {
78 mutable_state += 1;
79 break :blk1 @as(f64, 10.0);
80 } != blk2: {
81 try expect(mutable_state == 2);
82 break :blk2 @as(?f64, 5.0);
83 };
84}
85
86test "passing an optional integer as a parameter" {
87 const S = struct {
88 fn entry() bool {
89 var x: i32 = 1234;
90 return foo(x);
91 }
92
93 fn foo(x: ?i32) bool {
94 return x.? == 1234;
95 }
96 };
97 try expect(S.entry());
98 comptime try expect(S.entry());
99}
100
101test "unwrap function call with optional pointer return value" {
102 const S = struct {
103 fn entry() !void {
104 try expect(foo().?.* == 1234);
105 try expect(bar() == null);
106 }
107 const global: i32 = 1234;
108 fn foo() ?*const i32 {
109 return &global;
110 }
111 fn bar() ?*i32 {
112 return null;
113 }
114 };
115 try S.entry();
116 comptime try S.entry();
117}
118
119test "nested orelse" {
120 const S = struct {
121 fn entry() !void {
122 try expect(func() == null);
123 }
124 fn maybe() ?Foo {
125 return null;
126 }
127 fn func() ?Foo {
128 const x = maybe() orelse
129 maybe() orelse
130 return null;
131 unreachable;
132 }
133 const Foo = struct {
134 field: i32,
135 };
136 };
137 try S.entry();
138 comptime try S.entry();
139}
140
141test "self-referential struct through a slice of optional" {
142 const S = struct {
143 const Node = struct {
144 children: []?Node,
145 data: ?u8,
146
147 fn new() Node {
148 return Node{
149 .children = undefined,
150 .data = null,
151 };
152 }
153 };
154 };
155
156 var n = S.Node.new();
157 try expect(n.data == null);
158}
159
160test "assigning to an unwrapped optional field in an inline loop" {
161 comptime var maybe_pos_arg: ?comptime_int = null;
162 inline for ("ab") |x| {
163 maybe_pos_arg = 0;
164 if (maybe_pos_arg.? != 0) {
165 @compileError("bad");
166 }
167 maybe_pos_arg.? = 10;
168 }
169}
170
171test "coerce an anon struct literal to optional struct" {
172 const S = struct {
173 const Struct = struct {
174 field: u32,
175 };
176 fn doTheTest() !void {
177 var maybe_dims: ?Struct = null;
178 maybe_dims = .{ .field = 1 };
179 try expect(maybe_dims.?.field == 1);
180 }
181 };
182 try S.doTheTest();
183 comptime try S.doTheTest();
184}
185
186test "optional with void type" {
187 const Foo = struct {
188 x: ?void,
189 };
190 var x = Foo{ .x = null };
191 try expect(x.x == null);
192}
193
194test "0-bit child type coerced to optional return ptr result location" {
195 const S = struct {
196 fn doTheTest() !void {
197 var y = Foo{};
198 var z = y.thing();
199 try expect(z != null);
200 }
201
202 const Foo = struct {
203 pub const Bar = struct {
204 field: *Foo,
205 };
206
207 pub fn thing(self: *Foo) ?Bar {
208 return Bar{ .field = self };
209 }
210 };
211 };
212 try S.doTheTest();
213 comptime try S.doTheTest();
214}
215
216test "0-bit child type coerced to optional" {
217 const S = struct {
218 fn doTheTest() !void {
219 var it: Foo = .{
220 .list = undefined,
221 };
222 try expect(it.foo() != null);
223 }
224
225 const Empty = struct {};
226 const Foo = struct {
227 list: [10]Empty,
228
229 fn foo(self: *Foo) ?*Empty {
230 const data = &self.list[0];
231 return data;
232 }
233 };
234 };
235 try S.doTheTest();
236 comptime try S.doTheTest();
237}
238
239test "array of optional unaligned types" {
240 const Enum = enum { one, two, three };
241
242 const SomeUnion = union(enum) {
243 Num: Enum,
244 Other: u32,
245 };
246
247 const values = [_]?SomeUnion{
248 SomeUnion{ .Num = .one },
249 SomeUnion{ .Num = .two },
250 SomeUnion{ .Num = .three },
251 SomeUnion{ .Num = .one },
252 SomeUnion{ .Num = .two },
253 SomeUnion{ .Num = .three },
254 };
255
256 // The index must be a runtime value
257 var i: usize = 0;
258 try expectEqual(Enum.one, values[i].?.Num);
259 i += 1;
260 try expectEqual(Enum.two, values[i].?.Num);
261 i += 1;
262 try expectEqual(Enum.three, values[i].?.Num);
263 i += 1;
264 try expectEqual(Enum.one, values[i].?.Num);
265 i += 1;
266 try expectEqual(Enum.two, values[i].?.Num);
267 i += 1;
268 try expectEqual(Enum.three, values[i].?.Num);
269}
test/behavior/pointers.zig created+339
...@@ -0,0 +1,339 @@
1const std = @import("std");
2const testing = std.testing;
3const expect = testing.expect;
4const expectError = testing.expectError;
5
6test "dereference pointer" {
7 comptime try testDerefPtr();
8 try testDerefPtr();
9}
10
11fn testDerefPtr() !void {
12 var x: i32 = 1234;
13 var y = &x;
14 y.* += 1;
15 try expect(x == 1235);
16}
17
18const Foo1 = struct {
19 x: void,
20};
21
22test "dereference pointer again" {
23 try testDerefPtrOneVal();
24 comptime try testDerefPtrOneVal();
25}
26
27fn testDerefPtrOneVal() !void {
28 // Foo1 satisfies the OnePossibleValueYes criteria
29 const x = &Foo1{ .x = {} };
30 const y = x.*;
31 try expect(@TypeOf(y.x) == void);
32}
33
34test "pointer arithmetic" {
35 var ptr: [*]const u8 = "abcd";
36
37 try expect(ptr[0] == 'a');
38 ptr += 1;
39 try expect(ptr[0] == 'b');
40 ptr += 1;
41 try expect(ptr[0] == 'c');
42 ptr += 1;
43 try expect(ptr[0] == 'd');
44 ptr += 1;
45 try expect(ptr[0] == 0);
46 ptr -= 1;
47 try expect(ptr[0] == 'd');
48 ptr -= 1;
49 try expect(ptr[0] == 'c');
50 ptr -= 1;
51 try expect(ptr[0] == 'b');
52 ptr -= 1;
53 try expect(ptr[0] == 'a');
54}
55
56test "double pointer parsing" {
57 comptime try expect(PtrOf(PtrOf(i32)) == **i32);
58}
59
60fn PtrOf(comptime T: type) type {
61 return *T;
62}
63
64test "assigning integer to C pointer" {
65 var x: i32 = 0;
66 var ptr: [*c]u8 = 0;
67 var ptr2: [*c]u8 = x;
68}
69
70test "implicit cast single item pointer to C pointer and back" {
71 var y: u8 = 11;
72 var x: [*c]u8 = &y;
73 var z: *u8 = x;
74 z.* += 1;
75 try expect(y == 12);
76}
77
78test "C pointer comparison and arithmetic" {
79 const S = struct {
80 fn doTheTest() !void {
81 var one: usize = 1;
82 var ptr1: [*c]u32 = 0;
83 var ptr2 = ptr1 + 10;
84 try expect(ptr1 == 0);
85 try expect(ptr1 >= 0);
86 try expect(ptr1 <= 0);
87 // expect(ptr1 < 1);
88 // expect(ptr1 < one);
89 // expect(1 > ptr1);
90 // expect(one > ptr1);
91 try expect(ptr1 < ptr2);
92 try expect(ptr2 > ptr1);
93 try expect(ptr2 >= 40);
94 try expect(ptr2 == 40);
95 try expect(ptr2 <= 40);
96 ptr2 -= 10;
97 try expect(ptr1 == ptr2);
98 }
99 };
100 try S.doTheTest();
101 comptime try S.doTheTest();
102}
103
104test "peer type resolution with C pointers" {
105 var ptr_one: *u8 = undefined;
106 var ptr_many: [*]u8 = undefined;
107 var ptr_c: [*c]u8 = undefined;
108 var t = true;
109 var x1 = if (t) ptr_one else ptr_c;
110 var x2 = if (t) ptr_many else ptr_c;
111 var x3 = if (t) ptr_c else ptr_one;
112 var x4 = if (t) ptr_c else ptr_many;
113 try expect(@TypeOf(x1) == [*c]u8);
114 try expect(@TypeOf(x2) == [*c]u8);
115 try expect(@TypeOf(x3) == [*c]u8);
116 try expect(@TypeOf(x4) == [*c]u8);
117}
118
119test "implicit casting between C pointer and optional non-C pointer" {
120 var slice: []const u8 = "aoeu";
121 const opt_many_ptr: ?[*]const u8 = slice.ptr;
122 var ptr_opt_many_ptr = &opt_many_ptr;
123 var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
124 try expect(c_ptr.*.* == 'a');
125 ptr_opt_many_ptr = c_ptr;
126 try expect(ptr_opt_many_ptr.*.?[1] == 'o');
127}
128
129test "implicit cast error unions with non-optional to optional pointer" {
130 const S = struct {
131 fn doTheTest() !void {
132 try expectError(error.Fail, foo());
133 }
134 fn foo() anyerror!?*u8 {
135 return bar() orelse error.Fail;
136 }
137 fn bar() ?*u8 {
138 return null;
139 }
140 };
141 try S.doTheTest();
142 comptime try S.doTheTest();
143}
144
145test "initialize const optional C pointer to null" {
146 const a: ?[*c]i32 = null;
147 try expect(a == null);
148 comptime try expect(a == null);
149}
150
151test "compare equality of optional and non-optional pointer" {
152 const a = @intToPtr(*const usize, 0x12345678);
153 const b = @intToPtr(?*usize, 0x12345678);
154 try expect(a == b);
155 try expect(b == a);
156}
157
158test "allowzero pointer and slice" {
159 var ptr = @intToPtr([*]allowzero i32, 0);
160 var opt_ptr: ?[*]allowzero i32 = ptr;
161 try expect(opt_ptr != null);
162 try expect(@ptrToInt(ptr) == 0);
163 var runtime_zero: usize = 0;
164 var slice = ptr[runtime_zero..10];
165 comptime try expect(@TypeOf(slice) == []allowzero i32);
166 try expect(@ptrToInt(&slice[5]) == 20);
167
168 comptime try expect(@typeInfo(@TypeOf(ptr)).Pointer.is_allowzero);
169 comptime try expect(@typeInfo(@TypeOf(slice)).Pointer.is_allowzero);
170}
171
172test "assign null directly to C pointer and test null equality" {
173 var x: [*c]i32 = null;
174 try expect(x == null);
175 try expect(null == x);
176 try expect(!(x != null));
177 try expect(!(null != x));
178 if (x) |same_x| {
179 @panic("fail");
180 }
181 var otherx: i32 = undefined;
182 try expect((x orelse &otherx) == &otherx);
183
184 const y: [*c]i32 = null;
185 comptime try expect(y == null);
186 comptime try expect(null == y);
187 comptime try expect(!(y != null));
188 comptime try expect(!(null != y));
189 if (y) |same_y| @panic("fail");
190 const othery: i32 = undefined;
191 comptime try expect((y orelse &othery) == &othery);
192
193 var n: i32 = 1234;
194 var x1: [*c]i32 = &n;
195 try expect(!(x1 == null));
196 try expect(!(null == x1));
197 try expect(x1 != null);
198 try expect(null != x1);
199 try expect(x1.?.* == 1234);
200 if (x1) |same_x1| {
201 try expect(same_x1.* == 1234);
202 } else {
203 @panic("fail");
204 }
205 try expect((x1 orelse &otherx) == x1);
206
207 const nc: i32 = 1234;
208 const y1: [*c]const i32 = &nc;
209 comptime try expect(!(y1 == null));
210 comptime try expect(!(null == y1));
211 comptime try expect(y1 != null);
212 comptime try expect(null != y1);
213 comptime try expect(y1.?.* == 1234);
214 if (y1) |same_y1| {
215 try expect(same_y1.* == 1234);
216 } else {
217 @compileError("fail");
218 }
219 comptime try expect((y1 orelse &othery) == y1);
220}
221
222test "null terminated pointer" {
223 const S = struct {
224 fn doTheTest() !void {
225 var array_with_zero = [_:0]u8{ 'h', 'e', 'l', 'l', 'o' };
226 var zero_ptr: [*:0]const u8 = @ptrCast([*:0]const u8, &array_with_zero);
227 var no_zero_ptr: [*]const u8 = zero_ptr;
228 var zero_ptr_again = @ptrCast([*:0]const u8, no_zero_ptr);
229 try expect(std.mem.eql(u8, std.mem.spanZ(zero_ptr_again), "hello"));
230 }
231 };
232 try S.doTheTest();
233 comptime try S.doTheTest();
234}
235
236test "allow any sentinel" {
237 const S = struct {
238 fn doTheTest() !void {
239 var array = [_:std.math.minInt(i32)]i32{ 1, 2, 3, 4 };
240 var ptr: [*:std.math.minInt(i32)]i32 = &array;
241 try expect(ptr[4] == std.math.minInt(i32));
242 }
243 };
244 try S.doTheTest();
245 comptime try S.doTheTest();
246}
247
248test "pointer sentinel with enums" {
249 const S = struct {
250 const Number = enum {
251 one,
252 two,
253 sentinel,
254 };
255
256 fn doTheTest() !void {
257 var ptr: [*:.sentinel]const Number = &[_:.sentinel]Number{ .one, .two, .two, .one };
258 try expect(ptr[4] == .sentinel); // TODO this should be comptime try expect, see #3731
259 }
260 };
261 try S.doTheTest();
262 comptime try S.doTheTest();
263}
264
265test "pointer sentinel with optional element" {
266 const S = struct {
267 fn doTheTest() !void {
268 var ptr: [*:null]const ?i32 = &[_:null]?i32{ 1, 2, 3, 4 };
269 try expect(ptr[4] == null); // TODO this should be comptime try expect, see #3731
270 }
271 };
272 try S.doTheTest();
273 comptime try S.doTheTest();
274}
275
276test "pointer sentinel with +inf" {
277 const S = struct {
278 fn doTheTest() !void {
279 const inf = std.math.inf_f32;
280 var ptr: [*:inf]const f32 = &[_:inf]f32{ 1.1, 2.2, 3.3, 4.4 };
281 try expect(ptr[4] == inf); // TODO this should be comptime try expect, see #3731
282 }
283 };
284 try S.doTheTest();
285 comptime try S.doTheTest();
286}
287
288test "pointer to array at fixed address" {
289 const array = @intToPtr(*volatile [1]u32, 0x10);
290 // Silly check just to reference `array`
291 try expect(@ptrToInt(&array[0]) == 0x10);
292}
293
294test "pointer arithmetic affects the alignment" {
295 {
296 var ptr: [*]align(8) u32 = undefined;
297 var x: usize = 1;
298
299 try expect(@typeInfo(@TypeOf(ptr)).Pointer.alignment == 8);
300 const ptr1 = ptr + 1; // 1 * 4 = 4 -> lcd(4,8) = 4
301 try expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 4);
302 const ptr2 = ptr + 4; // 4 * 4 = 16 -> lcd(16,8) = 8
303 try expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 8);
304 const ptr3 = ptr + 0; // no-op
305 try expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
306 const ptr4 = ptr + x; // runtime-known addend
307 try expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
308 }
309 {
310 var ptr: [*]align(8) [3]u8 = undefined;
311 var x: usize = 1;
312
313 const ptr1 = ptr + 17; // 3 * 17 = 51
314 try expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 1);
315 const ptr2 = ptr + x; // runtime-known addend
316 try expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 1);
317 const ptr3 = ptr + 8; // 3 * 8 = 24 -> lcd(8,24) = 8
318 try expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
319 const ptr4 = ptr + 4; // 3 * 4 = 12 -> lcd(8,12) = 4
320 try expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
321 }
322}
323
324test "@ptrToInt on null optional at comptime" {
325 {
326 const pointer = @intToPtr(?*u8, 0x000);
327 const x = @ptrToInt(pointer);
328 comptime try expect(0 == @ptrToInt(pointer));
329 }
330 {
331 const pointer = @intToPtr(?*u8, 0xf00);
332 comptime try expect(0xf00 == @ptrToInt(pointer));
333 }
334}
335
336test "indexing array with sentinel returns correct type" {
337 var s: [:0]const u8 = "abc";
338 try testing.expectEqualSlices(u8, "*const u8", @typeName(@TypeOf(&s[0])));
339}
test/behavior/popcount.zig created+43
...@@ -0,0 +1,43 @@
1const expect = @import("std").testing.expect;
2
3test "@popCount" {
4 comptime try testPopCount();
5 try testPopCount();
6}
7
8fn testPopCount() !void {
9 {
10 var x: u32 = 0xffffffff;
11 try expect(@popCount(u32, x) == 32);
12 }
13 {
14 var x: u5 = 0x1f;
15 try expect(@popCount(u5, x) == 5);
16 }
17 {
18 var x: u32 = 0xaa;
19 try expect(@popCount(u32, x) == 4);
20 }
21 {
22 var x: u32 = 0xaaaaaaaa;
23 try expect(@popCount(u32, x) == 16);
24 }
25 {
26 var x: u32 = 0xaaaaaaaa;
27 try expect(@popCount(u32, x) == 16);
28 }
29 {
30 var x: i16 = -1;
31 try expect(@popCount(i16, x) == 16);
32 }
33 {
34 var x: i8 = -120;
35 try expect(@popCount(i8, x) == 2);
36 }
37 comptime {
38 try expect(@popCount(u8, @bitCast(u8, @as(i8, -120))) == 2);
39 }
40 comptime {
41 try expect(@popCount(i128, 0b11111111000110001100010000100001000011000011100101010001) == 24);
42 }
43}
test/behavior/ptrcast.zig created+73
...@@ -0,0 +1,73 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4const native_endian = builtin.target.cpu.arch.endian();
5
6test "reinterpret bytes as integer with nonzero offset" {
7 try testReinterpretBytesAsInteger();
8 comptime try testReinterpretBytesAsInteger();
9}
10
11fn testReinterpretBytesAsInteger() !void {
12 const bytes = "\x12\x34\x56\x78\xab";
13 const expected = switch (native_endian) {
14 .Little => 0xab785634,
15 .Big => 0x345678ab,
16 };
17 try expect(@ptrCast(*align(1) const u32, bytes[1..5]).* == expected);
18}
19
20test "reinterpret bytes of an array into an extern struct" {
21 try testReinterpretBytesAsExternStruct();
22 comptime try testReinterpretBytesAsExternStruct();
23}
24
25fn testReinterpretBytesAsExternStruct() !void {
26 var bytes align(2) = [_]u8{ 1, 2, 3, 4, 5, 6 };
27
28 const S = extern struct {
29 a: u8,
30 b: u16,
31 c: u8,
32 };
33
34 var ptr = @ptrCast(*const S, &bytes);
35 var val = ptr.c;
36 try expect(val == 5);
37}
38
39test "reinterpret struct field at comptime" {
40 const numNative = comptime Bytes.init(0x12345678);
41 if (native_endian != .Little) {
42 try expect(std.mem.eql(u8, &[_]u8{ 0x12, 0x34, 0x56, 0x78 }, &numNative.bytes));
43 } else {
44 try expect(std.mem.eql(u8, &[_]u8{ 0x78, 0x56, 0x34, 0x12 }, &numNative.bytes));
45 }
46}
47
48const Bytes = struct {
49 bytes: [4]u8,
50
51 pub fn init(v: u32) Bytes {
52 var res: Bytes = undefined;
53 @ptrCast(*align(1) u32, &res.bytes).* = v;
54
55 return res;
56 }
57};
58
59test "comptime ptrcast keeps larger alignment" {
60 comptime {
61 const a: u32 = 1234;
62 const p = @ptrCast([*]const u8, &a);
63 try expect(@TypeOf(p) == [*]align(@alignOf(u32)) const u8);
64 }
65}
66
67test "implicit optional pointer to optional c_void pointer" {
68 var buf: [4]u8 = "aoeu".*;
69 var x: ?[*]u8 = &buf;
70 var y: ?*c_void = x;
71 var z = @ptrCast(*[4]u8, y);
72 try expect(std.mem.eql(u8, z, "aoeu"));
73}
test/behavior/pub_enum.zig created+13
...@@ -0,0 +1,13 @@
1const other = @import("pub_enum/other.zig");
2const expect = @import("std").testing.expect;
3
4test "pub enum" {
5 try pubEnumTest(other.APubEnum.Two);
6}
7fn pubEnumTest(foo: other.APubEnum) !void {
8 try expect(foo == other.APubEnum.Two);
9}
10
11test "cast with imported symbol" {
12 try expect(@as(other.size_t, 42) == 42);
13}
test/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/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig created+37
...@@ -0,0 +1,37 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3
4var ok: bool = false;
5test "reference a variable in an if after an if in the 2nd switch prong" {
6 try foo(true, Num.Two, false, "aoeu");
7 try expect(!ok);
8 try foo(false, Num.One, false, "aoeu");
9 try expect(!ok);
10 try foo(true, Num.One, false, "aoeu");
11 try expect(ok);
12}
13
14const Num = enum {
15 One,
16 Two,
17};
18
19fn foo(c: bool, k: Num, c2: bool, b: []const u8) !void {
20 switch (k) {
21 Num.Two => {},
22 Num.One => {
23 if (c) {
24 const output_path = b;
25
26 if (c2) {}
27
28 try a(output_path);
29 }
30 },
31 }
32}
33
34fn a(x: []const u8) !void {
35 try expect(mem.eql(u8, x, "aoeu"));
36 ok = true;
37}
test/behavior/reflection.zig created+55
...@@ -0,0 +1,55 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3const reflection = @This();
4
5test "reflection: function return type, var args, and param types" {
6 comptime {
7 const info = @typeInfo(@TypeOf(dummy)).Fn;
8 try expect(info.return_type.? == i32);
9 try expect(!info.is_var_args);
10 try expect(info.args.len == 3);
11 try expect(info.args[0].arg_type.? == bool);
12 try expect(info.args[1].arg_type.? == i32);
13 try expect(info.args[2].arg_type.? == f32);
14 }
15}
16
17fn dummy(a: bool, b: i32, c: f32) i32 {
18 return 1234;
19}
20
21test "reflection: @field" {
22 var f = Foo{
23 .one = 42,
24 .two = true,
25 .three = void{},
26 };
27
28 try expect(f.one == f.one);
29 try expect(@field(f, "o" ++ "ne") == f.one);
30 try expect(@field(f, "t" ++ "wo") == f.two);
31 try expect(@field(f, "th" ++ "ree") == f.three);
32 try expect(@field(Foo, "const" ++ "ant") == Foo.constant);
33 try expect(@field(Bar, "O" ++ "ne") == Bar.One);
34 try expect(@field(Bar, "T" ++ "wo") == Bar.Two);
35 try expect(@field(Bar, "Th" ++ "ree") == Bar.Three);
36 try expect(@field(Bar, "F" ++ "our") == Bar.Four);
37 try expect(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
38 @field(f, "o" ++ "ne") = 4;
39 try expect(f.one == 4);
40}
41
42const Foo = struct {
43 const constant = 52;
44
45 one: i32,
46 two: bool,
47 three: void,
48};
49
50const Bar = union(enum) {
51 One: void,
52 Two: i32,
53 Three: bool,
54 Four: f64,
55};
test/behavior/shuffle.zig created+63
...@@ -0,0 +1,63 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const mem = std.mem;
4const expect = std.testing.expect;
5const Vector = std.meta.Vector;
6
7test "@shuffle" {
8 // TODO investigate why this fails when cross-compiling to wasm.
9 if (builtin.os.tag == .wasi) return error.SkipZigTest;
10
11 const S = struct {
12 fn doTheTest() !void {
13 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
14 var x: Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
15 const mask: Vector(4, i32) = [4]i32{ 0, ~@as(i32, 2), 3, ~@as(i32, 3) };
16 var res = @shuffle(i32, v, x, mask);
17 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, 40, 4 }));
18
19 // Implicit cast from array (of mask)
20 res = @shuffle(i32, v, x, [4]i32{ 0, ~@as(i32, 2), 3, ~@as(i32, 3) });
21 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, 40, 4 }));
22
23 // Undefined
24 const mask2: Vector(4, i32) = [4]i32{ 3, 1, 2, 0 };
25 res = @shuffle(i32, v, undefined, mask2);
26 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 40, -2, 30, 2147483647 }));
27
28 // Upcasting of b
29 var v2: Vector(2, i32) = [2]i32{ 2147483647, undefined };
30 const mask3: Vector(4, i32) = [4]i32{ ~@as(i32, 0), 2, ~@as(i32, 0), 3 };
31 res = @shuffle(i32, x, v2, mask3);
32 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, 2147483647, 4 }));
33
34 // Upcasting of a
35 var v3: Vector(2, i32) = [2]i32{ 2147483647, -2 };
36 const mask4: Vector(4, i32) = [4]i32{ 0, ~@as(i32, 2), 1, ~@as(i32, 3) };
37 res = @shuffle(i32, v3, x, mask4);
38 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, -2, 4 }));
39
40 // bool
41 // https://github.com/ziglang/zig/issues/3317
42 if (builtin.target.cpu.arch != .mipsel and builtin.target.cpu.arch != .mips) {
43 var x2: Vector(4, bool) = [4]bool{ false, true, false, true };
44 var v4: Vector(2, bool) = [2]bool{ true, false };
45 const mask5: Vector(4, i32) = [4]i32{ 0, ~@as(i32, 1), 1, 2 };
46 var res2 = @shuffle(bool, x2, v4, mask5);
47 try expect(mem.eql(bool, &@as([4]bool, res2), &[4]bool{ false, false, true, false }));
48 }
49
50 // TODO re-enable when LLVM codegen is fixed
51 // https://github.com/ziglang/zig/issues/3246
52 if (false) {
53 var x2: Vector(3, bool) = [3]bool{ false, true, false };
54 var v4: Vector(2, bool) = [2]bool{ true, false };
55 const mask5: Vector(4, i32) = [4]i32{ 0, ~@as(i32, 1), 1, 2 };
56 var res2 = @shuffle(bool, x2, v4, mask5);
57 try expect(mem.eql(bool, &@as([4]bool, res2), &[4]bool{ false, false, true, false }));
58 }
59 }
60 };
61 try S.doTheTest();
62 comptime try S.doTheTest();
63}
test/behavior/sizeof_and_typeof.zig created+264
...@@ -0,0 +1,264 @@
1const std = @import("std");
2const builtin = std.builtin;
3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;
5
6test "@sizeOf and @TypeOf" {
7 const y: @TypeOf(x) = 120;
8 try expect(@sizeOf(@TypeOf(y)) == 2);
9}
10const x: u16 = 13;
11const z: @TypeOf(x) = 19;
12
13const A = struct {
14 a: u8,
15 b: u32,
16 c: u8,
17 d: u3,
18 e: u5,
19 f: u16,
20 g: u16,
21 h: u9,
22 i: u7,
23};
24
25const P = packed struct {
26 a: u8,
27 b: u32,
28 c: u8,
29 d: u3,
30 e: u5,
31 f: u16,
32 g: u16,
33 h: u9,
34 i: u7,
35};
36
37test "@byteOffsetOf" {
38 // Packed structs have fixed memory layout
39 try expect(@byteOffsetOf(P, "a") == 0);
40 try expect(@byteOffsetOf(P, "b") == 1);
41 try expect(@byteOffsetOf(P, "c") == 5);
42 try expect(@byteOffsetOf(P, "d") == 6);
43 try expect(@byteOffsetOf(P, "e") == 6);
44 try expect(@byteOffsetOf(P, "f") == 7);
45 try expect(@byteOffsetOf(P, "g") == 9);
46 try expect(@byteOffsetOf(P, "h") == 11);
47 try expect(@byteOffsetOf(P, "i") == 12);
48
49 // Normal struct fields can be moved/padded
50 var a: A = undefined;
51 try expect(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
52 try expect(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
53 try expect(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
54 try expect(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
55 try expect(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
56 try expect(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
57 try expect(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
58 try expect(@ptrToInt(&a.h) - @ptrToInt(&a) == @byteOffsetOf(A, "h"));
59 try expect(@ptrToInt(&a.i) - @ptrToInt(&a) == @byteOffsetOf(A, "i"));
60}
61
62test "@byteOffsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" {
63 const p3a_len = 3;
64 const P3 = packed struct {
65 a: [p3a_len]u8,
66 b: usize,
67 };
68 try std.testing.expectEqual(0, @byteOffsetOf(P3, "a"));
69 try std.testing.expectEqual(p3a_len, @byteOffsetOf(P3, "b"));
70
71 const p5a_len = 5;
72 const P5 = packed struct {
73 a: [p5a_len]u8,
74 b: usize,
75 };
76 try std.testing.expectEqual(0, @byteOffsetOf(P5, "a"));
77 try std.testing.expectEqual(p5a_len, @byteOffsetOf(P5, "b"));
78
79 const p6a_len = 6;
80 const P6 = packed struct {
81 a: [p6a_len]u8,
82 b: usize,
83 };
84 try std.testing.expectEqual(0, @byteOffsetOf(P6, "a"));
85 try std.testing.expectEqual(p6a_len, @byteOffsetOf(P6, "b"));
86
87 const p7a_len = 7;
88 const P7 = packed struct {
89 a: [p7a_len]u8,
90 b: usize,
91 };
92 try std.testing.expectEqual(0, @byteOffsetOf(P7, "a"));
93 try std.testing.expectEqual(p7a_len, @byteOffsetOf(P7, "b"));
94
95 const p9a_len = 9;
96 const P9 = packed struct {
97 a: [p9a_len]u8,
98 b: usize,
99 };
100 try std.testing.expectEqual(0, @byteOffsetOf(P9, "a"));
101 try std.testing.expectEqual(p9a_len, @byteOffsetOf(P9, "b"));
102
103 // 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 25 etc. are further cases
104}
105
106test "@bitOffsetOf" {
107 // Packed structs have fixed memory layout
108 try expect(@bitOffsetOf(P, "a") == 0);
109 try expect(@bitOffsetOf(P, "b") == 8);
110 try expect(@bitOffsetOf(P, "c") == 40);
111 try expect(@bitOffsetOf(P, "d") == 48);
112 try expect(@bitOffsetOf(P, "e") == 51);
113 try expect(@bitOffsetOf(P, "f") == 56);
114 try expect(@bitOffsetOf(P, "g") == 72);
115
116 try expect(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
117 try expect(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
118 try expect(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
119 try expect(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
120 try expect(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
121 try expect(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
122 try expect(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
123}
124
125test "@sizeOf on compile-time types" {
126 try expect(@sizeOf(comptime_int) == 0);
127 try expect(@sizeOf(comptime_float) == 0);
128 try expect(@sizeOf(@TypeOf(.hi)) == 0);
129 try expect(@sizeOf(@TypeOf(type)) == 0);
130}
131
132test "@sizeOf(T) == 0 doesn't force resolving struct size" {
133 const S = struct {
134 const Foo = struct {
135 y: if (@sizeOf(Foo) == 0) u64 else u32,
136 };
137 const Bar = struct {
138 x: i32,
139 y: if (0 == @sizeOf(Bar)) u64 else u32,
140 };
141 };
142
143 try expect(@sizeOf(S.Foo) == 4);
144 try expect(@sizeOf(S.Bar) == 8);
145}
146
147test "@TypeOf() has no runtime side effects" {
148 const S = struct {
149 fn foo(comptime T: type, ptr: *T) T {
150 ptr.* += 1;
151 return ptr.*;
152 }
153 };
154 var data: i32 = 0;
155 const T = @TypeOf(S.foo(i32, &data));
156 comptime try expect(T == i32);
157 try expect(data == 0);
158}
159
160test "@TypeOf() with multiple arguments" {
161 {
162 var var_1: u32 = undefined;
163 var var_2: u8 = undefined;
164 var var_3: u64 = undefined;
165 comptime try expect(@TypeOf(var_1, var_2, var_3) == u64);
166 }
167 {
168 var var_1: f16 = undefined;
169 var var_2: f32 = undefined;
170 var var_3: f64 = undefined;
171 comptime try expect(@TypeOf(var_1, var_2, var_3) == f64);
172 }
173 {
174 var var_1: u16 = undefined;
175 comptime try expect(@TypeOf(var_1, 0xffff) == u16);
176 }
177 {
178 var var_1: f32 = undefined;
179 comptime try expect(@TypeOf(var_1, 3.1415) == f32);
180 }
181}
182
183test "branching logic inside @TypeOf" {
184 const S = struct {
185 var data: i32 = 0;
186 fn foo() anyerror!i32 {
187 data += 1;
188 return undefined;
189 }
190 };
191 const T = @TypeOf(S.foo() catch undefined);
192 comptime try expect(T == i32);
193 try expect(S.data == 0);
194}
195
196fn fn1(alpha: bool) void {
197 const n: usize = 7;
198 const v = if (alpha) n else @sizeOf(usize);
199}
200
201test "lazy @sizeOf result is checked for definedness" {
202 const f = fn1;
203}
204
205test "@bitSizeOf" {
206 try expect(@bitSizeOf(u2) == 2);
207 try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);
208 try expect(@bitSizeOf(struct {
209 a: u2,
210 }) == 8);
211 try expect(@bitSizeOf(packed struct {
212 a: u2,
213 }) == 2);
214}
215
216test "@sizeOf comparison against zero" {
217 const S0 = struct {
218 f: *@This(),
219 };
220 const U0 = union {
221 f: *@This(),
222 };
223 const S1 = struct {
224 fn H(comptime T: type) type {
225 return struct {
226 x: T,
227 };
228 }
229 f0: H(*@This()),
230 f1: H(**@This()),
231 f2: H(***@This()),
232 };
233 const U1 = union {
234 fn H(comptime T: type) type {
235 return struct {
236 x: T,
237 };
238 }
239 f0: H(*@This()),
240 f1: H(**@This()),
241 f2: H(***@This()),
242 };
243 const S = struct {
244 fn doTheTest(comptime T: type, comptime result: bool) !void {
245 try expectEqual(result, @sizeOf(T) > 0);
246 }
247 };
248 // Zero-sized type
249 try S.doTheTest(u0, false);
250 try S.doTheTest(*u0, false);
251 // Non byte-sized type
252 try S.doTheTest(u1, true);
253 try S.doTheTest(*u1, true);
254 // Regular type
255 try S.doTheTest(u8, true);
256 try S.doTheTest(*u8, true);
257 try S.doTheTest(f32, true);
258 try S.doTheTest(*f32, true);
259 // Container with ptr pointing to themselves
260 try S.doTheTest(S0, true);
261 try S.doTheTest(U0, true);
262 try S.doTheTest(S1, true);
263 try S.doTheTest(U1, true);
264}
test/behavior/slice.zig created+337
...@@ -0,0 +1,337 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
4const expectEqual = std.testing.expectEqual;
5const mem = std.mem;
6
7const x = @intToPtr([*]i32, 0x1000)[0..0x500];
8const y = x[0x100..];
9test "compile time slice of pointer to hard coded address" {
10 try expect(@ptrToInt(x) == 0x1000);
11 try expect(x.len == 0x500);
12
13 try expect(@ptrToInt(y) == 0x1100);
14 try expect(y.len == 0x400);
15}
16
17test "runtime safety lets us slice from len..len" {
18 var an_array = [_]u8{
19 1,
20 2,
21 3,
22 };
23 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
24}
25
26fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
27 return a_slice[start..end];
28}
29
30test "implicitly cast array of size 0 to slice" {
31 var msg = [_]u8{};
32 try assertLenIsZero(&msg);
33}
34
35fn assertLenIsZero(msg: []const u8) !void {
36 try expect(msg.len == 0);
37}
38
39test "C pointer" {
40 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
41 var len: u32 = 10;
42 var slice = buf[0..len];
43 try expectEqualSlices(u8, "kjdhfkjdhf", slice);
44}
45
46test "C pointer slice access" {
47 var buf: [10]u32 = [1]u32{42} ** 10;
48 const c_ptr = @ptrCast([*c]const u32, &buf);
49
50 var runtime_zero: usize = 0;
51 comptime try expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
52 comptime try expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
53
54 for (c_ptr[0..5]) |*cl| {
55 try expectEqual(@as(u32, 42), cl.*);
56 }
57}
58
59fn sliceSum(comptime q: []const u8) i32 {
60 comptime var result = 0;
61 inline for (q) |item| {
62 result += item;
63 }
64 return result;
65}
66
67test "comptime slices are disambiguated" {
68 try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
69 try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
70}
71
72test "slice type with custom alignment" {
73 const LazilyResolvedType = struct {
74 anything: i32,
75 };
76 var slice: []align(32) LazilyResolvedType = undefined;
77 var array: [10]LazilyResolvedType align(32) = undefined;
78 slice = &array;
79 slice[1].anything = 42;
80 try expect(array[1].anything == 42);
81}
82
83test "access len index of sentinel-terminated slice" {
84 const S = struct {
85 fn doTheTest() !void {
86 var slice: [:0]const u8 = "hello";
87
88 try expect(slice.len == 5);
89 try expect(slice[5] == 0);
90 }
91 };
92 try S.doTheTest();
93 comptime try S.doTheTest();
94}
95
96test "obtaining a null terminated slice" {
97 // here we have a normal array
98 var buf: [50]u8 = undefined;
99
100 buf[0] = 'a';
101 buf[1] = 'b';
102 buf[2] = 'c';
103 buf[3] = 0;
104
105 // now we obtain a null terminated slice:
106 const ptr = buf[0..3 :0];
107
108 var runtime_len: usize = 3;
109 const ptr2 = buf[0..runtime_len :0];
110 // ptr2 is a null-terminated slice
111 comptime try expect(@TypeOf(ptr2) == [:0]u8);
112 comptime try expect(@TypeOf(ptr2[0..2]) == *[2]u8);
113 var runtime_zero: usize = 0;
114 comptime try expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
115}
116
117test "empty array to slice" {
118 const S = struct {
119 fn doTheTest() !void {
120 const empty: []align(16) u8 = &[_]u8{};
121 const align_1: []align(1) u8 = empty;
122 const align_4: []align(4) u8 = empty;
123 const align_16: []align(16) u8 = empty;
124 try expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment);
125 try expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment);
126 try expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment);
127 }
128 };
129
130 try S.doTheTest();
131 comptime try S.doTheTest();
132}
133
134test "@ptrCast slice to pointer" {
135 const S = struct {
136 fn doTheTest() !void {
137 var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
138 var slice: []u8 = &array;
139 var ptr = @ptrCast(*u16, slice);
140 try expect(ptr.* == 65535);
141 }
142 };
143
144 try S.doTheTest();
145 comptime try S.doTheTest();
146}
147
148test "slice syntax resulting in pointer-to-array" {
149 const S = struct {
150 fn doTheTest() !void {
151 try testArray();
152 try testArrayZ();
153 try testArray0();
154 try testArrayAlign();
155 try testPointer();
156 try testPointerZ();
157 try testPointer0();
158 try testPointerAlign();
159 try testSlice();
160 try testSliceZ();
161 try testSlice0();
162 try testSliceOpt();
163 try testSliceAlign();
164 }
165
166 fn testArray() !void {
167 var array = [5]u8{ 1, 2, 3, 4, 5 };
168 var slice = array[1..3];
169 comptime try expect(@TypeOf(slice) == *[2]u8);
170 try expect(slice[0] == 2);
171 try expect(slice[1] == 3);
172 }
173
174 fn testArrayZ() !void {
175 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
176 comptime try expect(@TypeOf(array[1..3]) == *[2]u8);
177 comptime try expect(@TypeOf(array[1..5]) == *[4:0]u8);
178 comptime try expect(@TypeOf(array[1..]) == *[4:0]u8);
179 comptime try expect(@TypeOf(array[1..3 :4]) == *[2:4]u8);
180 }
181
182 fn testArray0() !void {
183 {
184 var array = [0]u8{};
185 var slice = array[0..0];
186 comptime try expect(@TypeOf(slice) == *[0]u8);
187 }
188 {
189 var array = [0:0]u8{};
190 var slice = array[0..0];
191 comptime try expect(@TypeOf(slice) == *[0:0]u8);
192 try expect(slice[0] == 0);
193 }
194 }
195
196 fn testArrayAlign() !void {
197 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
198 var slice = array[4..5];
199 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
200 try expect(slice[0] == 5);
201 comptime try expect(@TypeOf(array[0..2]) == *align(4) [2]u8);
202 }
203
204 fn testPointer() !void {
205 var array = [5]u8{ 1, 2, 3, 4, 5 };
206 var pointer: [*]u8 = &array;
207 var slice = pointer[1..3];
208 comptime try expect(@TypeOf(slice) == *[2]u8);
209 try expect(slice[0] == 2);
210 try expect(slice[1] == 3);
211 }
212
213 fn testPointerZ() !void {
214 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
215 var pointer: [*:0]u8 = &array;
216 comptime try expect(@TypeOf(pointer[1..3]) == *[2]u8);
217 comptime try expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
218 }
219
220 fn testPointer0() !void {
221 var pointer: [*]const u0 = &[1]u0{0};
222 var slice = pointer[0..1];
223 comptime try expect(@TypeOf(slice) == *const [1]u0);
224 try expect(slice[0] == 0);
225 }
226
227 fn testPointerAlign() !void {
228 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
229 var pointer: [*]align(4) u8 = &array;
230 var slice = pointer[4..5];
231 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
232 try expect(slice[0] == 5);
233 comptime try expect(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
234 }
235
236 fn testSlice() !void {
237 var array = [5]u8{ 1, 2, 3, 4, 5 };
238 var src_slice: []u8 = &array;
239 var slice = src_slice[1..3];
240 comptime try expect(@TypeOf(slice) == *[2]u8);
241 try expect(slice[0] == 2);
242 try expect(slice[1] == 3);
243 }
244
245 fn testSliceZ() !void {
246 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
247 var slice: [:0]u8 = &array;
248 comptime try expect(@TypeOf(slice[1..3]) == *[2]u8);
249 comptime try expect(@TypeOf(slice[1..]) == [:0]u8);
250 comptime try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
251 }
252
253 fn testSliceOpt() !void {
254 var array: [2]u8 = [2]u8{ 1, 2 };
255 var slice: ?[]u8 = &array;
256 comptime try expect(@TypeOf(&array, slice) == ?[]u8);
257 comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8);
258 }
259
260 fn testSlice0() !void {
261 {
262 var array = [0]u8{};
263 var src_slice: []u8 = &array;
264 var slice = src_slice[0..0];
265 comptime try expect(@TypeOf(slice) == *[0]u8);
266 }
267 {
268 var array = [0:0]u8{};
269 var src_slice: [:0]u8 = &array;
270 var slice = src_slice[0..0];
271 comptime try expect(@TypeOf(slice) == *[0]u8);
272 }
273 }
274
275 fn testSliceAlign() !void {
276 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
277 var src_slice: []align(4) u8 = &array;
278 var slice = src_slice[4..5];
279 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
280 try expect(slice[0] == 5);
281 comptime try expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
282 }
283
284 fn testConcatStrLiterals() !void {
285 try expectEqualSlices("a"[0..] ++ "b"[0..], "ab");
286 try expectEqualSlices("a"[0.. :0] ++ "b"[0.. :0], "ab");
287 }
288 };
289
290 try S.doTheTest();
291 comptime try S.doTheTest();
292}
293
294test "slice of hardcoded address to pointer" {
295 const S = struct {
296 fn doTheTest() !void {
297 const pointer = @intToPtr([*]u8, 0x04)[0..2];
298 comptime try expect(@TypeOf(pointer) == *[2]u8);
299 const slice: []const u8 = pointer;
300 try expect(@ptrToInt(slice.ptr) == 4);
301 try expect(slice.len == 2);
302 }
303 };
304
305 try S.doTheTest();
306}
307
308test "type coercion of pointer to anon struct literal to pointer to slice" {
309 const S = struct {
310 const U = union {
311 a: u32,
312 b: bool,
313 c: []const u8,
314 };
315
316 fn doTheTest() !void {
317 var x1: u8 = 42;
318 const t1 = &.{ x1, 56, 54 };
319 var slice1: []const u8 = t1;
320 try expect(slice1.len == 3);
321 try expect(slice1[0] == 42);
322 try expect(slice1[1] == 56);
323 try expect(slice1[2] == 54);
324
325 var x2: []const u8 = "hello";
326 const t2 = &.{ x2, ", ", "world!" };
327 // @compileLog(@TypeOf(t2));
328 var slice2: []const []const u8 = t2;
329 try expect(slice2.len == 3);
330 try expect(mem.eql(u8, slice2[0], "hello"));
331 try expect(mem.eql(u8, slice2[1], ", "));
332 try expect(mem.eql(u8, slice2[2], "world!"));
333 }
334 };
335 // try S.doTheTest();
336 comptime try S.doTheTest();
337}
test/behavior/slice_sentinel_comptime.zig created+199
...@@ -0,0 +1,199 @@
1test "comptime slice-sentinel in bounds (unterminated)" {
2 // array
3 comptime {
4 var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
5 const slice = target[0..3 :'d'];
6 }
7
8 // ptr_array
9 comptime {
10 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..3 :'d'];
13 }
14
15 // vector_ConstPtrSpecialBaseArray
16 comptime {
17 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
18 var target: [*]u8 = &buf;
19 const slice = target[0..3 :'d'];
20 }
21
22 // vector_ConstPtrSpecialRef
23 comptime {
24 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
25 var target: [*]u8 = @ptrCast([*]u8, &buf);
26 const slice = target[0..3 :'d'];
27 }
28
29 // cvector_ConstPtrSpecialBaseArray
30 comptime {
31 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
32 var target: [*c]u8 = &buf;
33 const slice = target[0..3 :'d'];
34 }
35
36 // cvector_ConstPtrSpecialRef
37 comptime {
38 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
39 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
40 const slice = target[0..3 :'d'];
41 }
42
43 // slice
44 comptime {
45 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
46 var target: []u8 = &buf;
47 const slice = target[0..3 :'d'];
48 }
49}
50
51test "comptime slice-sentinel in bounds (end,unterminated)" {
52 // array
53 comptime {
54 var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
55 const slice = target[0..13 :0xff];
56 }
57
58 // ptr_array
59 comptime {
60 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
61 var target = &buf;
62 const slice = target[0..13 :0xff];
63 }
64
65 // vector_ConstPtrSpecialBaseArray
66 comptime {
67 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
68 var target: [*]u8 = &buf;
69 const slice = target[0..13 :0xff];
70 }
71
72 // vector_ConstPtrSpecialRef
73 comptime {
74 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
75 var target: [*]u8 = @ptrCast([*]u8, &buf);
76 const slice = target[0..13 :0xff];
77 }
78
79 // cvector_ConstPtrSpecialBaseArray
80 comptime {
81 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
82 var target: [*c]u8 = &buf;
83 const slice = target[0..13 :0xff];
84 }
85
86 // cvector_ConstPtrSpecialRef
87 comptime {
88 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
89 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
90 const slice = target[0..13 :0xff];
91 }
92
93 // slice
94 comptime {
95 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
96 var target: []u8 = &buf;
97 const slice = target[0..13 :0xff];
98 }
99}
100
101test "comptime slice-sentinel in bounds (terminated)" {
102 // array
103 comptime {
104 var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
105 const slice = target[0..3 :'d'];
106 }
107
108 // ptr_array
109 comptime {
110 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
111 var target = &buf;
112 const slice = target[0..3 :'d'];
113 }
114
115 // vector_ConstPtrSpecialBaseArray
116 comptime {
117 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
118 var target: [*]u8 = &buf;
119 const slice = target[0..3 :'d'];
120 }
121
122 // vector_ConstPtrSpecialRef
123 comptime {
124 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
125 var target: [*]u8 = @ptrCast([*]u8, &buf);
126 const slice = target[0..3 :'d'];
127 }
128
129 // cvector_ConstPtrSpecialBaseArray
130 comptime {
131 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
132 var target: [*c]u8 = &buf;
133 const slice = target[0..3 :'d'];
134 }
135
136 // cvector_ConstPtrSpecialRef
137 comptime {
138 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
139 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
140 const slice = target[0..3 :'d'];
141 }
142
143 // slice
144 comptime {
145 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
146 var target: []u8 = &buf;
147 const slice = target[0..3 :'d'];
148 }
149}
150
151test "comptime slice-sentinel in bounds (on target sentinel)" {
152 // array
153 comptime {
154 var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
155 const slice = target[0..14 :0];
156 }
157
158 // ptr_array
159 comptime {
160 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
161 var target = &buf;
162 const slice = target[0..14 :0];
163 }
164
165 // vector_ConstPtrSpecialBaseArray
166 comptime {
167 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
168 var target: [*]u8 = &buf;
169 const slice = target[0..14 :0];
170 }
171
172 // vector_ConstPtrSpecialRef
173 comptime {
174 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
175 var target: [*]u8 = @ptrCast([*]u8, &buf);
176 const slice = target[0..14 :0];
177 }
178
179 // cvector_ConstPtrSpecialBaseArray
180 comptime {
181 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
182 var target: [*c]u8 = &buf;
183 const slice = target[0..14 :0];
184 }
185
186 // cvector_ConstPtrSpecialRef
187 comptime {
188 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
189 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
190 const slice = target[0..14 :0];
191 }
192
193 // slice
194 comptime {
195 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
196 var target: []u8 = &buf;
197 const slice = target[0..14 :0];
198 }
199}
test/behavior/src.zig created+17
...@@ -0,0 +1,17 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "@src" {
5 try doTheTest();
6}
7
8fn doTheTest() !void {
9 const src = @src();
10
11 try expect(src.line == 9);
12 try expect(src.column == 17);
13 try expect(std.mem.endsWith(u8, src.fn_name, "doTheTest"));
14 try expect(std.mem.endsWith(u8, src.file, "src.zig"));
15 try expect(src.fn_name[src.fn_name.len] == 0);
16 try expect(src.file[src.file.len] == 0);
17}
test/behavior/struct.zig created+946
...@@ -0,0 +1,946 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const native_endian = builtin.target.cpu.arch.endian();
4const expect = std.testing.expect;
5const expectEqual = std.testing.expectEqual;
6const expectEqualSlices = std.testing.expectEqualSlices;
7const maxInt = std.math.maxInt;
8const StructWithNoFields = struct {
9 fn add(a: i32, b: i32) i32 {
10 return a + b;
11 }
12};
13const empty_global_instance = StructWithNoFields{};
14
15top_level_field: i32,
16
17test "top level fields" {
18 var instance = @This(){
19 .top_level_field = 1234,
20 };
21 instance.top_level_field += 1;
22 try expectEqual(@as(i32, 1235), instance.top_level_field);
23}
24
25test "call struct static method" {
26 const result = StructWithNoFields.add(3, 4);
27 try expect(result == 7);
28}
29
30test "return empty struct instance" {
31 _ = returnEmptyStructInstance();
32}
33fn returnEmptyStructInstance() StructWithNoFields {
34 return empty_global_instance;
35}
36
37const should_be_11 = StructWithNoFields.add(5, 6);
38
39test "invoke static method in global scope" {
40 try expect(should_be_11 == 11);
41}
42
43test "void struct fields" {
44 const foo = VoidStructFieldsFoo{
45 .a = void{},
46 .b = 1,
47 .c = void{},
48 };
49 try expect(foo.b == 1);
50 try expect(@sizeOf(VoidStructFieldsFoo) == 4);
51}
52const VoidStructFieldsFoo = struct {
53 a: void,
54 b: i32,
55 c: void,
56};
57
58test "structs" {
59 var foo: StructFoo = undefined;
60 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
61 foo.a += 1;
62 foo.b = foo.a == 1;
63 try testFoo(foo);
64 testMutation(&foo);
65 try expect(foo.c == 100);
66}
67const StructFoo = struct {
68 a: i32,
69 b: bool,
70 c: f32,
71};
72fn testFoo(foo: StructFoo) !void {
73 try expect(foo.b);
74}
75fn testMutation(foo: *StructFoo) void {
76 foo.c = 100;
77}
78
79const Node = struct {
80 val: Val,
81 next: *Node,
82};
83
84const Val = struct {
85 x: i32,
86};
87
88test "struct point to self" {
89 var root: Node = undefined;
90 root.val.x = 1;
91
92 var node: Node = undefined;
93 node.next = &root;
94 node.val.x = 2;
95
96 root.next = &node;
97
98 try expect(node.next.next.next.val.x == 1);
99}
100
101test "struct byval assign" {
102 var foo1: StructFoo = undefined;
103 var foo2: StructFoo = undefined;
104
105 foo1.a = 1234;
106 foo2.a = 0;
107 try expect(foo2.a == 0);
108 foo2 = foo1;
109 try expect(foo2.a == 1234);
110}
111
112fn structInitializer() void {
113 const val = Val{ .x = 42 };
114 try expect(val.x == 42);
115}
116
117test "fn call of struct field" {
118 const Foo = struct {
119 ptr: fn () i32,
120 };
121 const S = struct {
122 fn aFunc() i32 {
123 return 13;
124 }
125
126 fn callStructField(foo: Foo) i32 {
127 return foo.ptr();
128 }
129 };
130
131 try expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13);
132}
133
134test "store member function in variable" {
135 const instance = MemberFnTestFoo{ .x = 1234 };
136 const memberFn = MemberFnTestFoo.member;
137 const result = memberFn(instance);
138 try expect(result == 1234);
139}
140const MemberFnTestFoo = struct {
141 x: i32,
142 fn member(foo: MemberFnTestFoo) i32 {
143 return foo.x;
144 }
145};
146
147test "call member function directly" {
148 const instance = MemberFnTestFoo{ .x = 1234 };
149 const result = MemberFnTestFoo.member(instance);
150 try expect(result == 1234);
151}
152
153test "member functions" {
154 const r = MemberFnRand{ .seed = 1234 };
155 try expect(r.getSeed() == 1234);
156}
157const MemberFnRand = struct {
158 seed: u32,
159 pub fn getSeed(r: *const MemberFnRand) u32 {
160 return r.seed;
161 }
162};
163
164test "return struct byval from function" {
165 const bar = makeBar(1234, 5678);
166 try expect(bar.y == 5678);
167}
168const Bar = struct {
169 x: i32,
170 y: i32,
171};
172fn makeBar(x: i32, y: i32) Bar {
173 return Bar{
174 .x = x,
175 .y = y,
176 };
177}
178
179test "empty struct method call" {
180 const es = EmptyStruct{};
181 try expect(es.method() == 1234);
182}
183const EmptyStruct = struct {
184 fn method(es: *const EmptyStruct) i32 {
185 return 1234;
186 }
187};
188
189test "return empty struct from fn" {
190 _ = testReturnEmptyStructFromFn();
191}
192const EmptyStruct2 = struct {};
193fn testReturnEmptyStructFromFn() EmptyStruct2 {
194 return EmptyStruct2{};
195}
196
197test "pass slice of empty struct to fn" {
198 try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1);
199}
200fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
201 return slice.len;
202}
203
204const APackedStruct = packed struct {
205 x: u8,
206 y: u8,
207};
208
209test "packed struct" {
210 var foo = APackedStruct{
211 .x = 1,
212 .y = 2,
213 };
214 foo.y += 1;
215 const four = foo.x + foo.y;
216 try expect(four == 4);
217}
218
219const BitField1 = packed struct {
220 a: u3,
221 b: u3,
222 c: u2,
223};
224
225const bit_field_1 = BitField1{
226 .a = 1,
227 .b = 2,
228 .c = 3,
229};
230
231test "bit field access" {
232 var data = bit_field_1;
233 try expect(getA(&data) == 1);
234 try expect(getB(&data) == 2);
235 try expect(getC(&data) == 3);
236 comptime try expect(@sizeOf(BitField1) == 1);
237
238 data.b += 1;
239 try expect(data.b == 3);
240
241 data.a += 1;
242 try expect(data.a == 2);
243 try expect(data.b == 3);
244}
245
246fn getA(data: *const BitField1) u3 {
247 return data.a;
248}
249
250fn getB(data: *const BitField1) u3 {
251 return data.b;
252}
253
254fn getC(data: *const BitField1) u2 {
255 return data.c;
256}
257
258const Foo24Bits = packed struct {
259 field: u24,
260};
261const Foo96Bits = packed struct {
262 a: u24,
263 b: u24,
264 c: u24,
265 d: u24,
266};
267
268test "packed struct 24bits" {
269 comptime {
270 try expect(@sizeOf(Foo24Bits) == 4);
271 if (@sizeOf(usize) == 4) {
272 try expect(@sizeOf(Foo96Bits) == 12);
273 } else {
274 try expect(@sizeOf(Foo96Bits) == 16);
275 }
276 }
277
278 var value = Foo96Bits{
279 .a = 0,
280 .b = 0,
281 .c = 0,
282 .d = 0,
283 };
284 value.a += 1;
285 try expect(value.a == 1);
286 try expect(value.b == 0);
287 try expect(value.c == 0);
288 try expect(value.d == 0);
289
290 value.b += 1;
291 try expect(value.a == 1);
292 try expect(value.b == 1);
293 try expect(value.c == 0);
294 try expect(value.d == 0);
295
296 value.c += 1;
297 try expect(value.a == 1);
298 try expect(value.b == 1);
299 try expect(value.c == 1);
300 try expect(value.d == 0);
301
302 value.d += 1;
303 try expect(value.a == 1);
304 try expect(value.b == 1);
305 try expect(value.c == 1);
306 try expect(value.d == 1);
307}
308
309const Foo32Bits = packed struct {
310 field: u24,
311 pad: u8,
312};
313
314const FooArray24Bits = packed struct {
315 a: u16,
316 b: [2]Foo32Bits,
317 c: u16,
318};
319
320// TODO revisit this test when doing https://github.com/ziglang/zig/issues/1512
321test "packed array 24bits" {
322 comptime {
323 try expect(@sizeOf([9]Foo32Bits) == 9 * 4);
324 try expect(@sizeOf(FooArray24Bits) == 2 + 2 * 4 + 2);
325 }
326
327 var bytes = [_]u8{0} ** (@sizeOf(FooArray24Bits) + 1);
328 bytes[bytes.len - 1] = 0xaa;
329 const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
330 try expect(ptr.a == 0);
331 try expect(ptr.b[0].field == 0);
332 try expect(ptr.b[1].field == 0);
333 try expect(ptr.c == 0);
334
335 ptr.a = maxInt(u16);
336 try expect(ptr.a == maxInt(u16));
337 try expect(ptr.b[0].field == 0);
338 try expect(ptr.b[1].field == 0);
339 try expect(ptr.c == 0);
340
341 ptr.b[0].field = maxInt(u24);
342 try expect(ptr.a == maxInt(u16));
343 try expect(ptr.b[0].field == maxInt(u24));
344 try expect(ptr.b[1].field == 0);
345 try expect(ptr.c == 0);
346
347 ptr.b[1].field = maxInt(u24);
348 try expect(ptr.a == maxInt(u16));
349 try expect(ptr.b[0].field == maxInt(u24));
350 try expect(ptr.b[1].field == maxInt(u24));
351 try expect(ptr.c == 0);
352
353 ptr.c = maxInt(u16);
354 try expect(ptr.a == maxInt(u16));
355 try expect(ptr.b[0].field == maxInt(u24));
356 try expect(ptr.b[1].field == maxInt(u24));
357 try expect(ptr.c == maxInt(u16));
358
359 try expect(bytes[bytes.len - 1] == 0xaa);
360}
361
362const FooStructAligned = packed struct {
363 a: u8,
364 b: u8,
365};
366
367const FooArrayOfAligned = packed struct {
368 a: [2]FooStructAligned,
369};
370
371test "aligned array of packed struct" {
372 comptime {
373 try expect(@sizeOf(FooStructAligned) == 2);
374 try expect(@sizeOf(FooArrayOfAligned) == 2 * 2);
375 }
376
377 var bytes = [_]u8{0xbb} ** @sizeOf(FooArrayOfAligned);
378 const ptr = &std.mem.bytesAsSlice(FooArrayOfAligned, bytes[0..])[0];
379
380 try expect(ptr.a[0].a == 0xbb);
381 try expect(ptr.a[0].b == 0xbb);
382 try expect(ptr.a[1].a == 0xbb);
383 try expect(ptr.a[1].b == 0xbb);
384}
385
386test "runtime struct initialization of bitfield" {
387 const s1 = Nibbles{
388 .x = x1,
389 .y = x1,
390 };
391 const s2 = Nibbles{
392 .x = @intCast(u4, x2),
393 .y = @intCast(u4, x2),
394 };
395
396 try expect(s1.x == x1);
397 try expect(s1.y == x1);
398 try expect(s2.x == @intCast(u4, x2));
399 try expect(s2.y == @intCast(u4, x2));
400}
401
402var x1 = @as(u4, 1);
403var x2 = @as(u8, 2);
404
405const Nibbles = packed struct {
406 x: u4,
407 y: u4,
408};
409
410const Bitfields = packed struct {
411 f1: u16,
412 f2: u16,
413 f3: u8,
414 f4: u8,
415 f5: u4,
416 f6: u4,
417 f7: u8,
418};
419
420test "native bit field understands endianness" {
421 var all: u64 = if (native_endian != .Little)
422 0x1111222233445677
423 else
424 0x7765443322221111;
425 var bytes: [8]u8 = undefined;
426 @memcpy(&bytes, @ptrCast([*]u8, &all), 8);
427 var bitfields = @ptrCast(*Bitfields, &bytes).*;
428
429 try expect(bitfields.f1 == 0x1111);
430 try expect(bitfields.f2 == 0x2222);
431 try expect(bitfields.f3 == 0x33);
432 try expect(bitfields.f4 == 0x44);
433 try expect(bitfields.f5 == 0x5);
434 try expect(bitfields.f6 == 0x6);
435 try expect(bitfields.f7 == 0x77);
436}
437
438test "align 1 field before self referential align 8 field as slice return type" {
439 const result = alloc(Expr);
440 try expect(result.len == 0);
441}
442
443const Expr = union(enum) {
444 Literal: u8,
445 Question: *Expr,
446};
447
448fn alloc(comptime T: type) []T {
449 return &[_]T{};
450}
451
452test "call method with mutable reference to struct with no fields" {
453 const S = struct {
454 fn doC(s: *const @This()) bool {
455 return true;
456 }
457 fn do(s: *@This()) bool {
458 return true;
459 }
460 };
461
462 var s = S{};
463 try expect(S.doC(&s));
464 try expect(s.doC());
465 try expect(S.do(&s));
466 try expect(s.do());
467}
468
469test "implicit cast packed struct field to const ptr" {
470 const LevelUpMove = packed struct {
471 move_id: u9,
472 level: u7,
473
474 fn toInt(value: u7) u7 {
475 return value;
476 }
477 };
478
479 var lup: LevelUpMove = undefined;
480 lup.level = 12;
481 const res = LevelUpMove.toInt(lup.level);
482 try expect(res == 12);
483}
484
485test "pointer to packed struct member in a stack variable" {
486 const S = packed struct {
487 a: u2,
488 b: u2,
489 };
490
491 var s = S{ .a = 2, .b = 0 };
492 var b_ptr = &s.b;
493 try expect(s.b == 0);
494 b_ptr.* = 2;
495 try expect(s.b == 2);
496}
497
498test "non-byte-aligned array inside packed struct" {
499 const Foo = packed struct {
500 a: bool,
501 b: [0x16]u8,
502 };
503 const S = struct {
504 fn bar(slice: []const u8) !void {
505 try expectEqualSlices(u8, slice, "abcdefghijklmnopqurstu");
506 }
507 fn doTheTest() !void {
508 var foo = Foo{
509 .a = true,
510 .b = "abcdefghijklmnopqurstu".*,
511 };
512 const value = foo.b;
513 try bar(&value);
514 }
515 };
516 try S.doTheTest();
517 comptime try S.doTheTest();
518}
519
520test "packed struct with u0 field access" {
521 const S = packed struct {
522 f0: u0,
523 };
524 var s = S{ .f0 = 0 };
525 comptime try expect(s.f0 == 0);
526}
527
528const S0 = struct {
529 bar: S1,
530
531 pub const S1 = struct {
532 value: u8,
533 };
534
535 fn init() @This() {
536 return S0{ .bar = S1{ .value = 123 } };
537 }
538};
539
540var g_foo: S0 = S0.init();
541
542test "access to global struct fields" {
543 g_foo.bar.value = 42;
544 try expect(g_foo.bar.value == 42);
545}
546
547test "packed struct with fp fields" {
548 const S = packed struct {
549 data: [3]f32,
550
551 pub fn frob(self: *@This()) void {
552 self.data[0] += self.data[1] + self.data[2];
553 self.data[1] += self.data[0] + self.data[2];
554 self.data[2] += self.data[0] + self.data[1];
555 }
556 };
557
558 var s: S = undefined;
559 s.data[0] = 1.0;
560 s.data[1] = 2.0;
561 s.data[2] = 3.0;
562 s.frob();
563 try expectEqual(@as(f32, 6.0), s.data[0]);
564 try expectEqual(@as(f32, 11.0), s.data[1]);
565 try expectEqual(@as(f32, 20.0), s.data[2]);
566}
567
568test "use within struct scope" {
569 const S = struct {
570 usingnamespace struct {
571 pub fn inner() i32 {
572 return 42;
573 }
574 };
575 };
576 try expectEqual(@as(i32, 42), S.inner());
577}
578
579test "default struct initialization fields" {
580 const S = struct {
581 a: i32 = 1234,
582 b: i32,
583 };
584 const x = S{
585 .b = 5,
586 };
587 if (x.a + x.b != 1239) {
588 @compileError("it should be comptime known");
589 }
590 var five: i32 = 5;
591 const y = S{
592 .b = five,
593 };
594 try expectEqual(1239, x.a + x.b);
595}
596
597test "fn with C calling convention returns struct by value" {
598 const S = struct {
599 fn entry() !void {
600 var x = makeBar(10);
601 try expectEqual(@as(i32, 10), x.handle);
602 }
603
604 const ExternBar = extern struct {
605 handle: i32,
606 };
607
608 fn makeBar(t: i32) callconv(.C) ExternBar {
609 return ExternBar{
610 .handle = t,
611 };
612 }
613 };
614 try S.entry();
615 comptime try S.entry();
616}
617
618test "for loop over pointers to struct, getting field from struct pointer" {
619 const S = struct {
620 const Foo = struct {
621 name: []const u8,
622 };
623
624 var ok = true;
625
626 fn eql(a: []const u8) bool {
627 return true;
628 }
629
630 const ArrayList = struct {
631 fn toSlice(self: *ArrayList) []*Foo {
632 return @as([*]*Foo, undefined)[0..0];
633 }
634 };
635
636 fn doTheTest() !void {
637 var objects: ArrayList = undefined;
638
639 for (objects.toSlice()) |obj| {
640 if (eql(obj.name)) {
641 ok = false;
642 }
643 }
644
645 try expect(ok);
646 }
647 };
648 try S.doTheTest();
649}
650
651test "zero-bit field in packed struct" {
652 const S = packed struct {
653 x: u10,
654 y: void,
655 };
656 var x: S = undefined;
657}
658
659test "struct field init with catch" {
660 const S = struct {
661 fn doTheTest() !void {
662 var x: anyerror!isize = 1;
663 var req = Foo{
664 .field = x catch undefined,
665 };
666 try expect(req.field == 1);
667 }
668
669 pub const Foo = extern struct {
670 field: isize,
671 };
672 };
673 try S.doTheTest();
674 comptime try S.doTheTest();
675}
676
677test "packed struct with non-ABI-aligned field" {
678 const S = packed struct {
679 x: u9,
680 y: u183,
681 };
682 var s: S = undefined;
683 s.x = 1;
684 s.y = 42;
685 try expect(s.x == 1);
686 try expect(s.y == 42);
687}
688
689test "non-packed struct with u128 entry in union" {
690 const U = union(enum) {
691 Num: u128,
692 Void,
693 };
694
695 const S = struct {
696 f1: U,
697 f2: U,
698 };
699
700 var sx: S = undefined;
701 var s = &sx;
702 try std.testing.expect(@ptrToInt(&s.f2) - @ptrToInt(&s.f1) == @byteOffsetOf(S, "f2"));
703 var v2 = U{ .Num = 123 };
704 s.f2 = v2;
705 try std.testing.expect(s.f2.Num == 123);
706}
707
708test "packed struct field passed to generic function" {
709 const S = struct {
710 const P = packed struct {
711 b: u5,
712 g: u5,
713 r: u5,
714 a: u1,
715 };
716
717 fn genericReadPackedField(ptr: anytype) u5 {
718 return ptr.*;
719 }
720 };
721
722 var p: S.P = undefined;
723 p.b = 29;
724 var loaded = S.genericReadPackedField(&p.b);
725 try expect(loaded == 29);
726}
727
728test "anonymous struct literal syntax" {
729 const S = struct {
730 const Point = struct {
731 x: i32,
732 y: i32,
733 };
734
735 fn doTheTest() !void {
736 var p: Point = .{
737 .x = 1,
738 .y = 2,
739 };
740 try expect(p.x == 1);
741 try expect(p.y == 2);
742 }
743 };
744 try S.doTheTest();
745 comptime try S.doTheTest();
746}
747
748test "fully anonymous struct" {
749 const S = struct {
750 fn doTheTest() !void {
751 try dump(.{
752 .int = @as(u32, 1234),
753 .float = @as(f64, 12.34),
754 .b = true,
755 .s = "hi",
756 });
757 }
758 fn dump(args: anytype) !void {
759 try expect(args.int == 1234);
760 try expect(args.float == 12.34);
761 try expect(args.b);
762 try expect(args.s[0] == 'h');
763 try expect(args.s[1] == 'i');
764 }
765 };
766 try S.doTheTest();
767 comptime try S.doTheTest();
768}
769
770test "fully anonymous list literal" {
771 const S = struct {
772 fn doTheTest() !void {
773 try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" });
774 }
775 fn dump(args: anytype) !void {
776 try expect(args.@"0" == 1234);
777 try expect(args.@"1" == 12.34);
778 try expect(args.@"2");
779 try expect(args.@"3"[0] == 'h');
780 try expect(args.@"3"[1] == 'i');
781 }
782 };
783 try S.doTheTest();
784 comptime try S.doTheTest();
785}
786
787test "anonymous struct literal assigned to variable" {
788 var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) };
789 try expect(vec.@"0" == 22);
790 try expect(vec.@"1" == 55);
791 try expect(vec.@"2" == 99);
792}
793
794test "struct with var field" {
795 const Point = struct {
796 x: anytype,
797 y: anytype,
798 };
799 const pt = Point{
800 .x = 1,
801 .y = 2,
802 };
803 try expect(pt.x == 1);
804 try expect(pt.y == 2);
805}
806
807test "comptime struct field" {
808 const T = struct {
809 a: i32,
810 comptime b: i32 = 1234,
811 };
812
813 var foo: T = undefined;
814 comptime try expect(foo.b == 1234);
815}
816
817test "anon struct literal field value initialized with fn call" {
818 const S = struct {
819 fn doTheTest() !void {
820 var x = .{foo()};
821 try expectEqualSlices(u8, x[0], "hi");
822 }
823 fn foo() []const u8 {
824 return "hi";
825 }
826 };
827 try S.doTheTest();
828 comptime try S.doTheTest();
829}
830
831test "self-referencing struct via array member" {
832 const T = struct {
833 children: [1]*@This(),
834 };
835 var x: T = undefined;
836 x = T{ .children = .{&x} };
837 try expect(x.children[0] == &x);
838}
839
840test "struct with union field" {
841 const Value = struct {
842 ref: u32 = 2,
843 kind: union(enum) {
844 None: usize,
845 Bool: bool,
846 },
847 };
848
849 var True = Value{
850 .kind = .{ .Bool = true },
851 };
852 try expectEqual(@as(u32, 2), True.ref);
853 try expectEqual(true, True.kind.Bool);
854}
855
856test "type coercion of anon struct literal to struct" {
857 const S = struct {
858 const S2 = struct {
859 A: u32,
860 B: []const u8,
861 C: void,
862 D: Foo = .{},
863 };
864
865 const Foo = struct {
866 field: i32 = 1234,
867 };
868
869 fn doTheTest() !void {
870 var y: u32 = 42;
871 const t0 = .{ .A = 123, .B = "foo", .C = {} };
872 const t1 = .{ .A = y, .B = "foo", .C = {} };
873 const y0: S2 = t0;
874 var y1: S2 = t1;
875 try expect(y0.A == 123);
876 try expect(std.mem.eql(u8, y0.B, "foo"));
877 try expect(y0.C == {});
878 try expect(y0.D.field == 1234);
879 try expect(y1.A == y);
880 try expect(std.mem.eql(u8, y1.B, "foo"));
881 try expect(y1.C == {});
882 try expect(y1.D.field == 1234);
883 }
884 };
885 try S.doTheTest();
886 comptime try S.doTheTest();
887}
888
889test "type coercion of pointer to anon struct literal to pointer to struct" {
890 const S = struct {
891 const S2 = struct {
892 A: u32,
893 B: []const u8,
894 C: void,
895 D: Foo = .{},
896 };
897
898 const Foo = struct {
899 field: i32 = 1234,
900 };
901
902 fn doTheTest() !void {
903 var y: u32 = 42;
904 const t0 = &.{ .A = 123, .B = "foo", .C = {} };
905 const t1 = &.{ .A = y, .B = "foo", .C = {} };
906 const y0: *const S2 = t0;
907 var y1: *const S2 = t1;
908 try expect(y0.A == 123);
909 try expect(std.mem.eql(u8, y0.B, "foo"));
910 try expect(y0.C == {});
911 try expect(y0.D.field == 1234);
912 try expect(y1.A == y);
913 try expect(std.mem.eql(u8, y1.B, "foo"));
914 try expect(y1.C == {});
915 try expect(y1.D.field == 1234);
916 }
917 };
918 try S.doTheTest();
919 comptime try S.doTheTest();
920}
921
922test "packed struct with undefined initializers" {
923 const S = struct {
924 const P = packed struct {
925 a: u3,
926 _a: u3 = undefined,
927 b: u3,
928 _b: u3 = undefined,
929 c: u3,
930 _c: u3 = undefined,
931 };
932
933 fn doTheTest() !void {
934 var p: P = undefined;
935 p = P{ .a = 2, .b = 4, .c = 6 };
936 // Make sure the compiler doesn't touch the unprefixed fields.
937 // Use expect since i386-linux doesn't like expectEqual
938 try expect(p.a == 2);
939 try expect(p.b == 4);
940 try expect(p.c == 6);
941 }
942 };
943
944 try S.doTheTest();
945 comptime try S.doTheTest();
946}
test/behavior/struct_contains_null_ptr_itself.zig created+21
...@@ -0,0 +1,21 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "struct contains null pointer which contains original struct" {
5 var x: ?*NodeLineComment = null;
6 try expect(x == null);
7}
8
9pub const Node = struct {
10 id: Id,
11 comment: ?*NodeLineComment,
12
13 pub const Id = enum {
14 Root,
15 LineComment,
16 };
17};
18
19pub const NodeLineComment = struct {
20 base: Node,
21};
test/behavior/struct_contains_slice_of_itself.zig created+85
...@@ -0,0 +1,85 @@
1const expect = @import("std").testing.expect;
2
3const Node = struct {
4 payload: i32,
5 children: []Node,
6};
7
8const NodeAligned = struct {
9 payload: i32,
10 children: []align(@alignOf(NodeAligned)) NodeAligned,
11};
12
13test "struct contains slice of itself" {
14 var other_nodes = [_]Node{
15 Node{
16 .payload = 31,
17 .children = &[_]Node{},
18 },
19 Node{
20 .payload = 32,
21 .children = &[_]Node{},
22 },
23 };
24 var nodes = [_]Node{
25 Node{
26 .payload = 1,
27 .children = &[_]Node{},
28 },
29 Node{
30 .payload = 2,
31 .children = &[_]Node{},
32 },
33 Node{
34 .payload = 3,
35 .children = other_nodes[0..],
36 },
37 };
38 const root = Node{
39 .payload = 1234,
40 .children = nodes[0..],
41 };
42 try expect(root.payload == 1234);
43 try expect(root.children[0].payload == 1);
44 try expect(root.children[1].payload == 2);
45 try expect(root.children[2].payload == 3);
46 try expect(root.children[2].children[0].payload == 31);
47 try expect(root.children[2].children[1].payload == 32);
48}
49
50test "struct contains aligned slice of itself" {
51 var other_nodes = [_]NodeAligned{
52 NodeAligned{
53 .payload = 31,
54 .children = &[_]NodeAligned{},
55 },
56 NodeAligned{
57 .payload = 32,
58 .children = &[_]NodeAligned{},
59 },
60 };
61 var nodes = [_]NodeAligned{
62 NodeAligned{
63 .payload = 1,
64 .children = &[_]NodeAligned{},
65 },
66 NodeAligned{
67 .payload = 2,
68 .children = &[_]NodeAligned{},
69 },
70 NodeAligned{
71 .payload = 3,
72 .children = other_nodes[0..],
73 },
74 };
75 const root = NodeAligned{
76 .payload = 1234,
77 .children = nodes[0..],
78 };
79 try expect(root.payload == 1234);
80 try expect(root.children[0].payload == 1);
81 try expect(root.children[1].payload == 2);
82 try expect(root.children[2].payload == 3);
83 try expect(root.children[2].children[0].payload == 31);
84 try expect(root.children[2].children[1].payload == 32);
85}
test/behavior/switch.zig created+537
...@@ -0,0 +1,537 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectError = std.testing.expectError;
4const expectEqual = std.testing.expectEqual;
5
6test "switch with numbers" {
7 try testSwitchWithNumbers(13);
8}
9
10fn testSwitchWithNumbers(x: u32) !void {
11 const result = switch (x) {
12 1, 2, 3, 4...8 => false,
13 13 => true,
14 else => false,
15 };
16 try expect(result);
17}
18
19test "switch with all ranges" {
20 try expect(testSwitchWithAllRanges(50, 3) == 1);
21 try expect(testSwitchWithAllRanges(101, 0) == 2);
22 try expect(testSwitchWithAllRanges(300, 5) == 3);
23 try expect(testSwitchWithAllRanges(301, 6) == 6);
24}
25
26fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
27 return switch (x) {
28 0...100 => 1,
29 101...200 => 2,
30 201...300 => 3,
31 else => y,
32 };
33}
34
35test "implicit comptime switch" {
36 const x = 3 + 4;
37 const result = switch (x) {
38 3 => 10,
39 4 => 11,
40 5, 6 => 12,
41 7, 8 => 13,
42 else => 14,
43 };
44
45 comptime {
46 try expect(result + 1 == 14);
47 }
48}
49
50test "switch on enum" {
51 const fruit = Fruit.Orange;
52 nonConstSwitchOnEnum(fruit);
53}
54const Fruit = enum {
55 Apple,
56 Orange,
57 Banana,
58};
59fn nonConstSwitchOnEnum(fruit: Fruit) void {
60 switch (fruit) {
61 Fruit.Apple => unreachable,
62 Fruit.Orange => {},
63 Fruit.Banana => unreachable,
64 }
65}
66
67test "switch statement" {
68 try nonConstSwitch(SwitchStatmentFoo.C);
69}
70fn nonConstSwitch(foo: SwitchStatmentFoo) !void {
71 const val = switch (foo) {
72 SwitchStatmentFoo.A => @as(i32, 1),
73 SwitchStatmentFoo.B => 2,
74 SwitchStatmentFoo.C => 3,
75 SwitchStatmentFoo.D => 4,
76 };
77 try expect(val == 3);
78}
79const SwitchStatmentFoo = enum {
80 A,
81 B,
82 C,
83 D,
84};
85
86test "switch prong with variable" {
87 try switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
88 try switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
89 try switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} });
90}
91const SwitchProngWithVarEnum = union(enum) {
92 One: i32,
93 Two: f32,
94 Meh: void,
95};
96fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {
97 switch (a) {
98 SwitchProngWithVarEnum.One => |x| {
99 try expect(x == 13);
100 },
101 SwitchProngWithVarEnum.Two => |x| {
102 try expect(x == 13.0);
103 },
104 SwitchProngWithVarEnum.Meh => |x| {
105 const v: void = x;
106 },
107 }
108}
109
110test "switch on enum using pointer capture" {
111 try testSwitchEnumPtrCapture();
112 comptime try testSwitchEnumPtrCapture();
113}
114
115fn testSwitchEnumPtrCapture() !void {
116 var value = SwitchProngWithVarEnum{ .One = 1234 };
117 switch (value) {
118 SwitchProngWithVarEnum.One => |*x| x.* += 1,
119 else => unreachable,
120 }
121 switch (value) {
122 SwitchProngWithVarEnum.One => |x| try expect(x == 1235),
123 else => unreachable,
124 }
125}
126
127test "switch with multiple expressions" {
128 const x = switch (returnsFive()) {
129 1, 2, 3 => 1,
130 4, 5, 6 => 2,
131 else => @as(i32, 3),
132 };
133 try expect(x == 2);
134}
135fn returnsFive() i32 {
136 return 5;
137}
138
139const Number = union(enum) {
140 One: u64,
141 Two: u8,
142 Three: f32,
143};
144
145const number = Number{ .Three = 1.23 };
146
147fn returnsFalse() bool {
148 switch (number) {
149 Number.One => |x| return x > 1234,
150 Number.Two => |x| return x == 'a',
151 Number.Three => |x| return x > 12.34,
152 }
153}
154test "switch on const enum with var" {
155 try expect(!returnsFalse());
156}
157
158test "switch on type" {
159 try expect(trueIfBoolFalseOtherwise(bool));
160 try expect(!trueIfBoolFalseOtherwise(i32));
161}
162
163fn trueIfBoolFalseOtherwise(comptime T: type) bool {
164 return switch (T) {
165 bool => true,
166 else => false,
167 };
168}
169
170test "switch handles all cases of number" {
171 try testSwitchHandleAllCases();
172 comptime try testSwitchHandleAllCases();
173}
174
175fn testSwitchHandleAllCases() !void {
176 try expect(testSwitchHandleAllCasesExhaustive(0) == 3);
177 try expect(testSwitchHandleAllCasesExhaustive(1) == 2);
178 try expect(testSwitchHandleAllCasesExhaustive(2) == 1);
179 try expect(testSwitchHandleAllCasesExhaustive(3) == 0);
180
181 try expect(testSwitchHandleAllCasesRange(100) == 0);
182 try expect(testSwitchHandleAllCasesRange(200) == 1);
183 try expect(testSwitchHandleAllCasesRange(201) == 2);
184 try expect(testSwitchHandleAllCasesRange(202) == 4);
185 try expect(testSwitchHandleAllCasesRange(230) == 3);
186}
187
188fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
189 return switch (x) {
190 0 => @as(u2, 3),
191 1 => 2,
192 2 => 1,
193 3 => 0,
194 };
195}
196
197fn testSwitchHandleAllCasesRange(x: u8) u8 {
198 return switch (x) {
199 0...100 => @as(u8, 0),
200 101...200 => 1,
201 201, 203 => 2,
202 202 => 4,
203 204...255 => 3,
204 };
205}
206
207test "switch all prongs unreachable" {
208 try testAllProngsUnreachable();
209 comptime try testAllProngsUnreachable();
210}
211
212fn testAllProngsUnreachable() !void {
213 try expect(switchWithUnreachable(1) == 2);
214 try expect(switchWithUnreachable(2) == 10);
215}
216
217fn switchWithUnreachable(x: i32) i32 {
218 while (true) {
219 switch (x) {
220 1 => return 2,
221 2 => break,
222 else => continue,
223 }
224 }
225 return 10;
226}
227
228fn return_a_number() anyerror!i32 {
229 return 1;
230}
231
232test "capture value of switch with all unreachable prongs" {
233 const x = return_a_number() catch |err| switch (err) {
234 else => unreachable,
235 };
236 try expect(x == 1);
237}
238
239test "switching on booleans" {
240 try testSwitchOnBools();
241 comptime try testSwitchOnBools();
242}
243
244fn testSwitchOnBools() !void {
245 try expect(testSwitchOnBoolsTrueAndFalse(true) == false);
246 try expect(testSwitchOnBoolsTrueAndFalse(false) == true);
247
248 try expect(testSwitchOnBoolsTrueWithElse(true) == false);
249 try expect(testSwitchOnBoolsTrueWithElse(false) == true);
250
251 try expect(testSwitchOnBoolsFalseWithElse(true) == false);
252 try expect(testSwitchOnBoolsFalseWithElse(false) == true);
253}
254
255fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
256 return switch (x) {
257 true => false,
258 false => true,
259 };
260}
261
262fn testSwitchOnBoolsTrueWithElse(x: bool) bool {
263 return switch (x) {
264 true => false,
265 else => true,
266 };
267}
268
269fn testSwitchOnBoolsFalseWithElse(x: bool) bool {
270 return switch (x) {
271 false => true,
272 else => false,
273 };
274}
275
276test "u0" {
277 var val: u0 = 0;
278 switch (val) {
279 0 => try expect(val == 0),
280 }
281}
282
283test "undefined.u0" {
284 var val: u0 = undefined;
285 switch (val) {
286 0 => try expect(val == 0),
287 }
288}
289
290test "anon enum literal used in switch on union enum" {
291 const Foo = union(enum) {
292 a: i32,
293 };
294
295 var foo = Foo{ .a = 1234 };
296 switch (foo) {
297 .a => |x| {
298 try expect(x == 1234);
299 },
300 }
301}
302
303test "else prong of switch on error set excludes other cases" {
304 const S = struct {
305 fn doTheTest() !void {
306 try expectError(error.C, bar());
307 }
308 const E = error{
309 A,
310 B,
311 } || E2;
312
313 const E2 = error{
314 C,
315 D,
316 };
317
318 fn foo() E!void {
319 return error.C;
320 }
321
322 fn bar() E2!void {
323 foo() catch |err| switch (err) {
324 error.A, error.B => {},
325 else => |e| return e,
326 };
327 }
328 };
329 try S.doTheTest();
330 comptime try S.doTheTest();
331}
332
333test "switch prongs with error set cases make a new error set type for capture value" {
334 const S = struct {
335 fn doTheTest() !void {
336 try expectError(error.B, bar());
337 }
338 const E = E1 || E2;
339
340 const E1 = error{
341 A,
342 B,
343 };
344
345 const E2 = error{
346 C,
347 D,
348 };
349
350 fn foo() E!void {
351 return error.B;
352 }
353
354 fn bar() E1!void {
355 foo() catch |err| switch (err) {
356 error.A, error.B => |e| return e,
357 else => {},
358 };
359 }
360 };
361 try S.doTheTest();
362 comptime try S.doTheTest();
363}
364
365test "return result loc and then switch with range implicit casted to error union" {
366 const S = struct {
367 fn doTheTest() !void {
368 try expect((func(0xb) catch unreachable) == 0xb);
369 }
370 fn func(d: u8) anyerror!u8 {
371 return switch (d) {
372 0xa...0xf => d,
373 else => unreachable,
374 };
375 }
376 };
377 try S.doTheTest();
378 comptime try S.doTheTest();
379}
380
381test "switch with null and T peer types and inferred result location type" {
382 const S = struct {
383 fn doTheTest(c: u8) !void {
384 if (switch (c) {
385 0 => true,
386 else => null,
387 }) |v| {
388 @panic("fail");
389 }
390 }
391 };
392 try S.doTheTest(1);
393 comptime try S.doTheTest(1);
394}
395
396test "switch prongs with cases with identical payload types" {
397 const Union = union(enum) {
398 A: usize,
399 B: isize,
400 C: usize,
401 };
402 const S = struct {
403 fn doTheTest() !void {
404 try doTheSwitch1(Union{ .A = 8 });
405 try doTheSwitch2(Union{ .B = -8 });
406 }
407 fn doTheSwitch1(u: Union) !void {
408 switch (u) {
409 .A, .C => |e| {
410 try expect(@TypeOf(e) == usize);
411 try expect(e == 8);
412 },
413 .B => |e| @panic("fail"),
414 }
415 }
416 fn doTheSwitch2(u: Union) !void {
417 switch (u) {
418 .A, .C => |e| @panic("fail"),
419 .B => |e| {
420 try expect(@TypeOf(e) == isize);
421 try expect(e == -8);
422 },
423 }
424 }
425 };
426 try S.doTheTest();
427 comptime try S.doTheTest();
428}
429
430test "switch with disjoint range" {
431 var q: u8 = 0;
432 switch (q) {
433 0...125 => {},
434 127...255 => {},
435 126...126 => {},
436 }
437}
438
439test "switch variable for range and multiple prongs" {
440 const S = struct {
441 fn doTheTest() !void {
442 var u: u8 = 16;
443 try doTheSwitch(u);
444 comptime try doTheSwitch(u);
445 var v: u8 = 42;
446 try doTheSwitch(v);
447 comptime try doTheSwitch(v);
448 }
449 fn doTheSwitch(q: u8) !void {
450 switch (q) {
451 0...40 => |x| try expect(x == 16),
452 41, 42, 43 => |x| try expect(x == 42),
453 else => try expect(false),
454 }
455 }
456 };
457}
458
459var state: u32 = 0;
460fn poll() void {
461 switch (state) {
462 0 => {
463 state = 1;
464 },
465 else => {
466 state += 1;
467 },
468 }
469}
470
471test "switch on global mutable var isn't constant-folded" {
472 while (state < 2) {
473 poll();
474 }
475}
476
477test "switch on pointer type" {
478 const S = struct {
479 const X = struct {
480 field: u32,
481 };
482
483 const P1 = @intToPtr(*X, 0x400);
484 const P2 = @intToPtr(*X, 0x800);
485 const P3 = @intToPtr(*X, 0xC00);
486
487 fn doTheTest(arg: *X) i32 {
488 switch (arg) {
489 P1 => return 1,
490 P2 => return 2,
491 else => return 3,
492 }
493 }
494 };
495
496 try expect(1 == S.doTheTest(S.P1));
497 try expect(2 == S.doTheTest(S.P2));
498 try expect(3 == S.doTheTest(S.P3));
499 comptime try expect(1 == S.doTheTest(S.P1));
500 comptime try expect(2 == S.doTheTest(S.P2));
501 comptime try expect(3 == S.doTheTest(S.P3));
502}
503
504test "switch on error set with single else" {
505 const S = struct {
506 fn doTheTest() !void {
507 var some: error{Foo} = error.Foo;
508 try expect(switch (some) {
509 else => |a| true,
510 });
511 }
512 };
513
514 try S.doTheTest();
515 comptime try S.doTheTest();
516}
517
518test "while copies its payload" {
519 const S = struct {
520 fn doTheTest() !void {
521 var tmp: union(enum) {
522 A: u8,
523 B: u32,
524 } = .{ .A = 42 };
525 switch (tmp) {
526 .A => |value| {
527 // Modify the original union
528 tmp = .{ .B = 0x10101010 };
529 try expectEqual(@as(u8, 42), value);
530 },
531 else => unreachable,
532 }
533 }
534 };
535 try S.doTheTest();
536 comptime try S.doTheTest();
537}
test/behavior/switch_prong_err_enum.zig created+30
...@@ -0,0 +1,30 @@
1const expect = @import("std").testing.expect;
2
3var read_count: u64 = 0;
4
5fn readOnce() anyerror!u64 {
6 read_count += 1;
7 return read_count;
8}
9
10const FormValue = union(enum) {
11 Address: u64,
12 Other: bool,
13};
14
15fn doThing(form_id: u64) anyerror!FormValue {
16 return switch (form_id) {
17 17 => FormValue{ .Address = try readOnce() },
18 else => error.InvalidDebugInfo,
19 };
20}
21
22test "switch prong returns error enum" {
23 switch (doThing(17) catch unreachable) {
24 FormValue.Address => |payload| {
25 try expect(payload == 1);
26 },
27 else => unreachable,
28 }
29 try expect(read_count == 1);
30}
test/behavior/switch_prong_implicit_cast.zig created+22
...@@ -0,0 +1,22 @@
1const expect = @import("std").testing.expect;
2
3const FormValue = union(enum) {
4 One: void,
5 Two: bool,
6};
7
8fn foo(id: u64) !FormValue {
9 return switch (id) {
10 2 => FormValue{ .Two = true },
11 1 => FormValue{ .One = {} },
12 else => return error.Whatever,
13 };
14}
15
16test "switch prong implicit cast" {
17 const result = switch (foo(2) catch unreachable) {
18 FormValue.One => false,
19 FormValue.Two => |x| x,
20 };
21 try expect(result);
22}
test/behavior/syntax.zig created+68
...@@ -0,0 +1,68 @@
1// Test trailing comma syntax
2// zig fmt: off
3
4extern var a: c_int;
5extern "c" var b: c_int;
6export var c: c_int = 0;
7threadlocal var d: c_int;
8extern threadlocal var e: c_int;
9extern "c" threadlocal var f: c_int;
10export threadlocal var g: c_int = 0;
11
12const struct_trailing_comma = struct { x: i32, y: i32, };
13const struct_no_comma = struct { x: i32, y: i32 };
14const struct_fn_no_comma = struct { fn m() void {} y: i32 };
15
16const enum_no_comma = enum { A, B };
17
18fn container_init() void {
19 const S = struct { x: i32, y: i32 };
20 _ = S { .x = 1, .y = 2 };
21 _ = S { .x = 1, .y = 2, };
22}
23
24fn type_expr_return1() if (true) A {}
25fn type_expr_return2() for (true) |_| A {}
26fn type_expr_return3() while (true) A {}
27fn type_expr_return4() comptime A {}
28
29fn switch_cases(x: i32) void {
30 switch (x) {
31 1,2,3 => {},
32 4,5, => {},
33 6...8, => {},
34 else => {},
35 }
36}
37
38fn switch_prongs(x: i32) void {
39 switch (x) {
40 0 => {},
41 else => {},
42 }
43 switch (x) {
44 0 => {},
45 else => {}
46 }
47}
48
49const fn_no_comma = fn(i32, i32)void;
50const fn_trailing_comma = fn(i32, i32,)void;
51
52fn fn_calls() void {
53 fn add(x: i32, y: i32,) i32 { x + y };
54 _ = add(1, 2);
55 _ = add(1, 2,);
56}
57
58fn asm_lists() void {
59 if (false) { // Build AST but don't analyze
60 asm ("not real assembly"
61 :[a] "x" (x),);
62 asm ("not real assembly"
63 :[a] "x" (->i32),:[a] "x" (1),);
64 asm ("still not real assembly"
65 :::"a","b",);
66 }
67}
68
test/behavior/this.zig created+34
...@@ -0,0 +1,34 @@
1const expect = @import("std").testing.expect;
2
3const module = @This();
4
5fn Point(comptime T: type) type {
6 return struct {
7 const Self = @This();
8 x: T,
9 y: T,
10
11 fn addOne(self: *Self) void {
12 self.x += 1;
13 self.y += 1;
14 }
15 };
16}
17
18fn add(x: i32, y: i32) i32 {
19 return x + y;
20}
21
22test "this refer to module call private fn" {
23 try expect(module.add(1, 2) == 3);
24}
25
26test "this refer to container" {
27 var pt = Point(i32){
28 .x = 12,
29 .y = 34,
30 };
31 pt.addOne();
32 try expect(pt.x == 13);
33 try expect(pt.y == 35);
34}
test/behavior/translate_c_macros.h created+18
...@@ -0,0 +1,18 @@
1// initializer list expression
2typedef struct Color {
3 unsigned char r;
4 unsigned char g;
5 unsigned char b;
6 unsigned char a;
7} Color;
8#define CLITERAL(type) (type)
9#define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray
10
11#define MY_SIZEOF(x) ((int)sizeof(x))
12#define MY_SIZEOF2(x) ((int)sizeof x)
13
14struct Foo {
15 int a;
16};
17
18#define SIZE_OF_FOO sizeof(struct Foo)
test/behavior/translate_c_macros.zig created+22
...@@ -0,0 +1,22 @@
1const expect = @import("std").testing.expect;
2const expectEqual = @import("std").testing.expectEqual;
3
4const h = @cImport(@cInclude("behavior/translate_c_macros.h"));
5
6test "initializer list expression" {
7 try expectEqual(h.Color{
8 .r = 200,
9 .g = 200,
10 .b = 200,
11 .a = 255,
12 }, h.LIGHTGRAY);
13}
14
15test "sizeof in macros" {
16 try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
17 try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
18}
19
20test "reference to a struct type" {
21 try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);
22}
test/behavior/truncate.zig created+36
...@@ -0,0 +1,36 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "truncate u0 to larger integer allowed and has comptime known result" {
5 var x: u0 = 0;
6 const y = @truncate(u8, x);
7 comptime try expect(y == 0);
8}
9
10test "truncate.u0.literal" {
11 var z = @truncate(u0, 0);
12 try expect(z == 0);
13}
14
15test "truncate.u0.const" {
16 const c0: usize = 0;
17 var z = @truncate(u0, c0);
18 try expect(z == 0);
19}
20
21test "truncate.u0.var" {
22 var d: u8 = 2;
23 var z = @truncate(u0, d);
24 try expect(z == 0);
25}
26
27test "truncate sign mismatch but comptime known so it works anyway" {
28 const x: u32 = 10;
29 var result = @truncate(i8, x);
30 try expect(result == 10);
31}
32
33test "truncate on comptime integer" {
34 var x = @truncate(u16, 9999);
35 try expect(x == 9999);
36}
test/behavior/try.zig created+43
...@@ -0,0 +1,43 @@
1const expect = @import("std").testing.expect;
2
3test "try on error union" {
4 try tryOnErrorUnionImpl();
5 comptime try 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 => @as(i32, 2),
12 else => unreachable,
13 };
14 try expect(x == 11);
15}
16
17fn returnsTen() anyerror!i32 {
18 return 10;
19}
20
21test "try without vars" {
22 const result1 = if (failIfTrue(true)) 1 else |_| @as(i32, 2);
23 try expect(result1 == 2);
24
25 const result2 = if (failIfTrue(false)) 1 else |_| @as(i32, 2);
26 try expect(result2 == 1);
27}
28
29fn failIfTrue(ok: bool) anyerror!void {
30 if (ok) {
31 return error.ItBroke;
32 } else {
33 return;
34 }
35}
36
37test "try then not executed with assignment" {
38 if (failIfTrue(true)) {
39 unreachable;
40 } else |err| {
41 try expect(err == error.ItBroke);
42 }
43}
test/behavior/tuple.zig created+113
...@@ -0,0 +1,113 @@
1const std = @import("std");
2const testing = std.testing;
3const expect = testing.expect;
4const expectEqual = testing.expectEqual;
5
6test "tuple concatenation" {
7 const S = struct {
8 fn doTheTest() !void {
9 var a: i32 = 1;
10 var b: i32 = 2;
11 var x = .{a};
12 var y = .{b};
13 var c = x ++ y;
14 try expectEqual(@as(i32, 1), c[0]);
15 try expectEqual(@as(i32, 2), c[1]);
16 }
17 };
18 try S.doTheTest();
19 comptime try S.doTheTest();
20}
21
22test "tuple multiplication" {
23 const S = struct {
24 fn doTheTest() !void {
25 {
26 const t = .{} ** 4;
27 try expectEqual(0, @typeInfo(@TypeOf(t)).Struct.fields.len);
28 }
29 {
30 const t = .{'a'} ** 4;
31 try expectEqual(4, @typeInfo(@TypeOf(t)).Struct.fields.len);
32 inline for (t) |x| try expectEqual('a', x);
33 }
34 {
35 const t = .{ 1, 2, 3 } ** 4;
36 try expectEqual(12, @typeInfo(@TypeOf(t)).Struct.fields.len);
37 inline for (t) |x, i| try expectEqual(1 + i % 3, x);
38 }
39 }
40 };
41 try S.doTheTest();
42 comptime try S.doTheTest();
43
44 const T = struct {
45 fn consume_tuple(tuple: anytype, len: usize) !void {
46 try expect(tuple.len == len);
47 }
48
49 fn doTheTest() !void {
50 const t1 = .{};
51
52 var rt_var: u8 = 42;
53 const t2 = .{rt_var} ++ .{};
54
55 try expect(t2.len == 1);
56 try expect(t2.@"0" == rt_var);
57 try expect(t2.@"0" == 42);
58 try expect(&t2.@"0" != &rt_var);
59
60 try consume_tuple(t1 ++ t1, 0);
61 try consume_tuple(.{} ++ .{}, 0);
62 try consume_tuple(.{0} ++ .{}, 1);
63 try consume_tuple(.{0} ++ .{1}, 2);
64 try consume_tuple(.{ 0, 1, 2 } ++ .{ u8, 1, noreturn }, 6);
65 try consume_tuple(t2 ++ t1, 1);
66 try consume_tuple(t1 ++ t2, 1);
67 try consume_tuple(t2 ++ t2, 2);
68 try consume_tuple(.{rt_var} ++ .{}, 1);
69 try consume_tuple(.{rt_var} ++ t1, 1);
70 try consume_tuple(.{} ++ .{rt_var}, 1);
71 try consume_tuple(t2 ++ .{void}, 2);
72 try consume_tuple(t2 ++ .{0}, 2);
73 try consume_tuple(.{0} ++ t2, 2);
74 try consume_tuple(.{void} ++ t2, 2);
75 try consume_tuple(.{u8} ++ .{rt_var} ++ .{true}, 3);
76 }
77 };
78
79 try T.doTheTest();
80 comptime try T.doTheTest();
81}
82
83test "pass tuple to comptime var parameter" {
84 const S = struct {
85 fn Foo(comptime args: anytype) !void {
86 try expect(args[0] == 1);
87 }
88
89 fn doTheTest() !void {
90 try Foo(.{1});
91 }
92 };
93 try S.doTheTest();
94 comptime try S.doTheTest();
95}
96
97test "tuple initializer for var" {
98 const S = struct {
99 fn doTheTest() void {
100 const Bytes = struct {
101 id: usize,
102 };
103
104 var tmp = .{
105 .id = @as(usize, 2),
106 .name = Bytes{ .id = 20 },
107 };
108 }
109 };
110
111 S.doTheTest();
112 comptime S.doTheTest();
113}
test/behavior/type.zig created+453
...@@ -0,0 +1,453 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const TypeInfo = std.builtin.TypeInfo;
4const testing = std.testing;
5
6fn testTypes(comptime types: []const type) !void {
7 inline for (types) |testType| {
8 try testing.expect(testType == @Type(@typeInfo(testType)));
9 }
10}
11
12test "Type.MetaType" {
13 try testing.expect(type == @Type(TypeInfo{ .Type = undefined }));
14 try testTypes(&[_]type{type});
15}
16
17test "Type.Void" {
18 try testing.expect(void == @Type(TypeInfo{ .Void = undefined }));
19 try testTypes(&[_]type{void});
20}
21
22test "Type.Bool" {
23 try testing.expect(bool == @Type(TypeInfo{ .Bool = undefined }));
24 try testTypes(&[_]type{bool});
25}
26
27test "Type.NoReturn" {
28 try testing.expect(noreturn == @Type(TypeInfo{ .NoReturn = undefined }));
29 try testTypes(&[_]type{noreturn});
30}
31
32test "Type.Int" {
33 try testing.expect(u1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .unsigned, .bits = 1 } }));
34 try testing.expect(i1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .signed, .bits = 1 } }));
35 try testing.expect(u8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .unsigned, .bits = 8 } }));
36 try testing.expect(i8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .signed, .bits = 8 } }));
37 try testing.expect(u64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .unsigned, .bits = 64 } }));
38 try testing.expect(i64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .signed, .bits = 64 } }));
39 try testTypes(&[_]type{ u8, u32, i64 });
40}
41
42test "Type.Float" {
43 try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } }));
44 try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } }));
45 try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } }));
46 try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } }));
47 try testTypes(&[_]type{ f16, f32, f64, f128 });
48}
49
50test "Type.Pointer" {
51 try testTypes(&[_]type{
52 // One Value Pointer Types
53 *u8, *const u8,
54 *volatile u8, *const volatile u8,
55 *align(4) u8, *align(4) const u8,
56 *align(4) volatile u8, *align(4) const volatile u8,
57 *align(8) u8, *align(8) const u8,
58 *align(8) volatile u8, *align(8) const volatile u8,
59 *allowzero u8, *allowzero const u8,
60 *allowzero volatile u8, *allowzero const volatile u8,
61 *allowzero align(4) u8, *allowzero align(4) const u8,
62 *allowzero align(4) volatile u8, *allowzero align(4) const volatile u8,
63 // Many Values Pointer Types
64 [*]u8, [*]const u8,
65 [*]volatile u8, [*]const volatile u8,
66 [*]align(4) u8, [*]align(4) const u8,
67 [*]align(4) volatile u8, [*]align(4) const volatile u8,
68 [*]align(8) u8, [*]align(8) const u8,
69 [*]align(8) volatile u8, [*]align(8) const volatile u8,
70 [*]allowzero u8, [*]allowzero const u8,
71 [*]allowzero volatile u8, [*]allowzero const volatile u8,
72 [*]allowzero align(4) u8, [*]allowzero align(4) const u8,
73 [*]allowzero align(4) volatile u8, [*]allowzero align(4) const volatile u8,
74 // Slice Types
75 []u8, []const u8,
76 []volatile u8, []const volatile u8,
77 []align(4) u8, []align(4) const u8,
78 []align(4) volatile u8, []align(4) const volatile u8,
79 []align(8) u8, []align(8) const u8,
80 []align(8) volatile u8, []align(8) const volatile u8,
81 []allowzero u8, []allowzero const u8,
82 []allowzero volatile u8, []allowzero const volatile u8,
83 []allowzero align(4) u8, []allowzero align(4) const u8,
84 []allowzero align(4) volatile u8, []allowzero align(4) const volatile u8,
85 // C Pointer Types
86 [*c]u8, [*c]const u8,
87 [*c]volatile u8, [*c]const volatile u8,
88 [*c]align(4) u8, [*c]align(4) const u8,
89 [*c]align(4) volatile u8, [*c]align(4) const volatile u8,
90 [*c]align(8) u8, [*c]align(8) const u8,
91 [*c]align(8) volatile u8, [*c]align(8) const volatile u8,
92 });
93}
94
95test "Type.Array" {
96 try testing.expect([123]u8 == @Type(TypeInfo{
97 .Array = TypeInfo.Array{
98 .len = 123,
99 .child = u8,
100 .sentinel = null,
101 },
102 }));
103 try testing.expect([2]u32 == @Type(TypeInfo{
104 .Array = TypeInfo.Array{
105 .len = 2,
106 .child = u32,
107 .sentinel = null,
108 },
109 }));
110 try testing.expect([2:0]u32 == @Type(TypeInfo{
111 .Array = TypeInfo.Array{
112 .len = 2,
113 .child = u32,
114 .sentinel = 0,
115 },
116 }));
117 try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool });
118}
119
120test "Type.ComptimeFloat" {
121 try testTypes(&[_]type{comptime_float});
122}
123test "Type.ComptimeInt" {
124 try testTypes(&[_]type{comptime_int});
125}
126test "Type.Undefined" {
127 try testTypes(&[_]type{@TypeOf(undefined)});
128}
129test "Type.Null" {
130 try testTypes(&[_]type{@TypeOf(null)});
131}
132test "@Type create slice with null sentinel" {
133 const Slice = @Type(TypeInfo{
134 .Pointer = .{
135 .size = .Slice,
136 .is_const = true,
137 .is_volatile = false,
138 .is_allowzero = false,
139 .alignment = 8,
140 .child = *i32,
141 .sentinel = null,
142 },
143 });
144 try testing.expect(Slice == []align(8) const *i32);
145}
146test "@Type picks up the sentinel value from TypeInfo" {
147 try testTypes(&[_]type{
148 [11:0]u8, [4:10]u8,
149 [*:0]u8, [*:0]const u8,
150 [*:0]volatile u8, [*:0]const volatile u8,
151 [*:0]align(4) u8, [*:0]align(4) const u8,
152 [*:0]align(4) volatile u8, [*:0]align(4) const volatile u8,
153 [*:0]align(8) u8, [*:0]align(8) const u8,
154 [*:0]align(8) volatile u8, [*:0]align(8) const volatile u8,
155 [*:0]allowzero u8, [*:0]allowzero const u8,
156 [*:0]allowzero volatile u8, [*:0]allowzero const volatile u8,
157 [*:0]allowzero align(4) u8, [*:0]allowzero align(4) const u8,
158 [*:0]allowzero align(4) volatile u8, [*:0]allowzero align(4) const volatile u8,
159 [*:5]allowzero align(4) volatile u8, [*:5]allowzero align(4) const volatile u8,
160 [:0]u8, [:0]const u8,
161 [:0]volatile u8, [:0]const volatile u8,
162 [:0]align(4) u8, [:0]align(4) const u8,
163 [:0]align(4) volatile u8, [:0]align(4) const volatile u8,
164 [:0]align(8) u8, [:0]align(8) const u8,
165 [:0]align(8) volatile u8, [:0]align(8) const volatile u8,
166 [:0]allowzero u8, [:0]allowzero const u8,
167 [:0]allowzero volatile u8, [:0]allowzero const volatile u8,
168 [:0]allowzero align(4) u8, [:0]allowzero align(4) const u8,
169 [:0]allowzero align(4) volatile u8, [:0]allowzero align(4) const volatile u8,
170 [:4]allowzero align(4) volatile u8, [:4]allowzero align(4) const volatile u8,
171 });
172}
173
174test "Type.Optional" {
175 try testTypes(&[_]type{
176 ?u8,
177 ?*u8,
178 ?[]u8,
179 ?[*]u8,
180 ?[*c]u8,
181 });
182}
183
184test "Type.ErrorUnion" {
185 try testTypes(&[_]type{
186 error{}!void,
187 error{Error}!void,
188 });
189}
190
191test "Type.Opaque" {
192 const Opaque = @Type(.{
193 .Opaque = .{
194 .decls = &[_]TypeInfo.Declaration{},
195 },
196 });
197 try testing.expect(Opaque != opaque {});
198 try testing.expectEqualSlices(
199 TypeInfo.Declaration,
200 &[_]TypeInfo.Declaration{},
201 @typeInfo(Opaque).Opaque.decls,
202 );
203}
204
205test "Type.Vector" {
206 try testTypes(&[_]type{
207 @Vector(0, u8),
208 @Vector(4, u8),
209 @Vector(8, *u8),
210 std.meta.Vector(0, u8),
211 std.meta.Vector(4, u8),
212 std.meta.Vector(8, *u8),
213 });
214}
215
216test "Type.AnyFrame" {
217 try testTypes(&[_]type{
218 anyframe,
219 anyframe->u8,
220 anyframe->anyframe->u8,
221 });
222}
223
224test "Type.EnumLiteral" {
225 try testTypes(&[_]type{
226 @TypeOf(.Dummy),
227 });
228}
229
230fn add(a: i32, b: i32) i32 {
231 return a + b;
232}
233
234test "Type.Frame" {
235 try testTypes(&[_]type{
236 @Frame(add),
237 });
238}
239
240test "Type.ErrorSet" {
241 // error sets don't compare equal so just check if they compile
242 _ = @Type(@typeInfo(error{}));
243 _ = @Type(@typeInfo(error{A}));
244 _ = @Type(@typeInfo(error{ A, B, C }));
245}
246
247test "Type.Struct" {
248 const A = @Type(@typeInfo(struct { x: u8, y: u32 }));
249 const infoA = @typeInfo(A).Struct;
250 try testing.expectEqual(TypeInfo.ContainerLayout.Auto, infoA.layout);
251 try testing.expectEqualSlices(u8, "x", infoA.fields[0].name);
252 try testing.expectEqual(u8, infoA.fields[0].field_type);
253 try testing.expectEqual(@as(?u8, null), infoA.fields[0].default_value);
254 try testing.expectEqualSlices(u8, "y", infoA.fields[1].name);
255 try testing.expectEqual(u32, infoA.fields[1].field_type);
256 try testing.expectEqual(@as(?u32, null), infoA.fields[1].default_value);
257 try testing.expectEqualSlices(TypeInfo.Declaration, &[_]TypeInfo.Declaration{}, infoA.decls);
258 try testing.expectEqual(@as(bool, false), infoA.is_tuple);
259
260 var a = A{ .x = 0, .y = 1 };
261 try testing.expectEqual(@as(u8, 0), a.x);
262 try testing.expectEqual(@as(u32, 1), a.y);
263 a.y += 1;
264 try testing.expectEqual(@as(u32, 2), a.y);
265
266 const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 }));
267 const infoB = @typeInfo(B).Struct;
268 try testing.expectEqual(TypeInfo.ContainerLayout.Extern, infoB.layout);
269 try testing.expectEqualSlices(u8, "x", infoB.fields[0].name);
270 try testing.expectEqual(u8, infoB.fields[0].field_type);
271 try testing.expectEqual(@as(?u8, null), infoB.fields[0].default_value);
272 try testing.expectEqualSlices(u8, "y", infoB.fields[1].name);
273 try testing.expectEqual(u32, infoB.fields[1].field_type);
274 try testing.expectEqual(@as(?u32, 5), infoB.fields[1].default_value);
275 try testing.expectEqual(@as(usize, 0), infoB.decls.len);
276 try testing.expectEqual(@as(bool, false), infoB.is_tuple);
277
278 const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 }));
279 const infoC = @typeInfo(C).Struct;
280 try testing.expectEqual(TypeInfo.ContainerLayout.Packed, infoC.layout);
281 try testing.expectEqualSlices(u8, "x", infoC.fields[0].name);
282 try testing.expectEqual(u8, infoC.fields[0].field_type);
283 try testing.expectEqual(@as(?u8, 3), infoC.fields[0].default_value);
284 try testing.expectEqualSlices(u8, "y", infoC.fields[1].name);
285 try testing.expectEqual(u32, infoC.fields[1].field_type);
286 try testing.expectEqual(@as(?u32, 5), infoC.fields[1].default_value);
287 try testing.expectEqual(@as(usize, 0), infoC.decls.len);
288 try testing.expectEqual(@as(bool, false), infoC.is_tuple);
289}
290
291test "Type.Enum" {
292 const Foo = @Type(.{
293 .Enum = .{
294 .layout = .Auto,
295 .tag_type = u8,
296 .fields = &[_]TypeInfo.EnumField{
297 .{ .name = "a", .value = 1 },
298 .{ .name = "b", .value = 5 },
299 },
300 .decls = &[_]TypeInfo.Declaration{},
301 .is_exhaustive = true,
302 },
303 });
304 try testing.expectEqual(true, @typeInfo(Foo).Enum.is_exhaustive);
305 try testing.expectEqual(@as(u8, 1), @enumToInt(Foo.a));
306 try testing.expectEqual(@as(u8, 5), @enumToInt(Foo.b));
307 const Bar = @Type(.{
308 .Enum = .{
309 .layout = .Extern,
310 .tag_type = u32,
311 .fields = &[_]TypeInfo.EnumField{
312 .{ .name = "a", .value = 1 },
313 .{ .name = "b", .value = 5 },
314 },
315 .decls = &[_]TypeInfo.Declaration{},
316 .is_exhaustive = false,
317 },
318 });
319 try testing.expectEqual(false, @typeInfo(Bar).Enum.is_exhaustive);
320 try testing.expectEqual(@as(u32, 1), @enumToInt(Bar.a));
321 try testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b));
322 try testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6)));
323}
324
325test "Type.Union" {
326 const Untagged = @Type(.{
327 .Union = .{
328 .layout = .Auto,
329 .tag_type = null,
330 .fields = &[_]TypeInfo.UnionField{
331 .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) },
332 .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) },
333 },
334 .decls = &[_]TypeInfo.Declaration{},
335 },
336 });
337 var untagged = Untagged{ .int = 1 };
338 untagged.float = 2.0;
339 untagged.int = 3;
340 try testing.expectEqual(@as(i32, 3), untagged.int);
341
342 const PackedUntagged = @Type(.{
343 .Union = .{
344 .layout = .Packed,
345 .tag_type = null,
346 .fields = &[_]TypeInfo.UnionField{
347 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
348 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
349 },
350 .decls = &[_]TypeInfo.Declaration{},
351 },
352 });
353 var packed_untagged = PackedUntagged{ .signed = -1 };
354 try testing.expectEqual(@as(i32, -1), packed_untagged.signed);
355 try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned);
356
357 const Tag = @Type(.{
358 .Enum = .{
359 .layout = .Auto,
360 .tag_type = u1,
361 .fields = &[_]TypeInfo.EnumField{
362 .{ .name = "signed", .value = 0 },
363 .{ .name = "unsigned", .value = 1 },
364 },
365 .decls = &[_]TypeInfo.Declaration{},
366 .is_exhaustive = true,
367 },
368 });
369 const Tagged = @Type(.{
370 .Union = .{
371 .layout = .Auto,
372 .tag_type = Tag,
373 .fields = &[_]TypeInfo.UnionField{
374 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
375 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
376 },
377 .decls = &[_]TypeInfo.Declaration{},
378 },
379 });
380 var tagged = Tagged{ .signed = -1 };
381 try testing.expectEqual(Tag.signed, tagged);
382 tagged = .{ .unsigned = 1 };
383 try testing.expectEqual(Tag.unsigned, tagged);
384}
385
386test "Type.Union from Type.Enum" {
387 const Tag = @Type(.{
388 .Enum = .{
389 .layout = .Auto,
390 .tag_type = u0,
391 .fields = &[_]TypeInfo.EnumField{
392 .{ .name = "working_as_expected", .value = 0 },
393 },
394 .decls = &[_]TypeInfo.Declaration{},
395 .is_exhaustive = true,
396 },
397 });
398 const T = @Type(.{
399 .Union = .{
400 .layout = .Auto,
401 .tag_type = Tag,
402 .fields = &[_]TypeInfo.UnionField{
403 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
404 },
405 .decls = &[_]TypeInfo.Declaration{},
406 },
407 });
408 _ = T;
409 _ = @typeInfo(T).Union;
410}
411
412test "Type.Union from regular enum" {
413 const E = enum { working_as_expected = 0 };
414 const T = @Type(.{
415 .Union = .{
416 .layout = .Auto,
417 .tag_type = E,
418 .fields = &[_]TypeInfo.UnionField{
419 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
420 },
421 .decls = &[_]TypeInfo.Declaration{},
422 },
423 });
424 _ = T;
425 _ = @typeInfo(T).Union;
426}
427
428test "Type.Fn" {
429 // wasm doesn't support align attributes on functions
430 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
431
432 const foo = struct {
433 fn func(a: usize, b: bool) align(4) callconv(.C) usize {
434 return 0;
435 }
436 }.func;
437 const Foo = @Type(@typeInfo(@TypeOf(foo)));
438 const foo_2: Foo = foo;
439}
440
441test "Type.BoundFn" {
442 // wasm doesn't support align attributes on functions
443 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
444
445 const TestStruct = packed struct {
446 pub fn foo(self: *const @This()) align(4) callconv(.Unspecified) void {}
447 };
448 const test_instance: TestStruct = undefined;
449 try testing.expect(std.meta.eql(
450 @typeName(@TypeOf(test_instance.foo)),
451 @typeName(@Type(@typeInfo(@TypeOf(test_instance.foo)))),
452 ));
453}
test/behavior/type_info.zig created+484
...@@ -0,0 +1,484 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const mem = std.mem;
4
5const TypeInfo = std.builtin.TypeInfo;
6const TypeId = std.builtin.TypeId;
7
8const expect = std.testing.expect;
9const expectEqualStrings = std.testing.expectEqualStrings;
10
11test "type info: tag type, void info" {
12 try testBasic();
13 comptime try testBasic();
14}
15
16fn testBasic() !void {
17 try expect(@typeInfo(TypeInfo).Union.tag_type == TypeId);
18 const void_info = @typeInfo(void);
19 try expect(void_info == TypeId.Void);
20 try expect(void_info.Void == {});
21}
22
23test "type info: integer, floating point type info" {
24 try testIntFloat();
25 comptime try testIntFloat();
26}
27
28fn testIntFloat() !void {
29 const u8_info = @typeInfo(u8);
30 try expect(u8_info == .Int);
31 try expect(u8_info.Int.signedness == .unsigned);
32 try expect(u8_info.Int.bits == 8);
33
34 const f64_info = @typeInfo(f64);
35 try expect(f64_info == .Float);
36 try expect(f64_info.Float.bits == 64);
37}
38
39test "type info: pointer type info" {
40 try testPointer();
41 comptime try testPointer();
42}
43
44fn testPointer() !void {
45 const u32_ptr_info = @typeInfo(*u32);
46 try expect(u32_ptr_info == .Pointer);
47 try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
48 try expect(u32_ptr_info.Pointer.is_const == false);
49 try expect(u32_ptr_info.Pointer.is_volatile == false);
50 try expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
51 try expect(u32_ptr_info.Pointer.child == u32);
52 try expect(u32_ptr_info.Pointer.sentinel == null);
53}
54
55test "type info: unknown length pointer type info" {
56 try testUnknownLenPtr();
57 comptime try testUnknownLenPtr();
58}
59
60fn testUnknownLenPtr() !void {
61 const u32_ptr_info = @typeInfo([*]const volatile f64);
62 try expect(u32_ptr_info == .Pointer);
63 try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
64 try expect(u32_ptr_info.Pointer.is_const == true);
65 try expect(u32_ptr_info.Pointer.is_volatile == true);
66 try expect(u32_ptr_info.Pointer.sentinel == null);
67 try expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
68 try expect(u32_ptr_info.Pointer.child == f64);
69}
70
71test "type info: null terminated pointer type info" {
72 try testNullTerminatedPtr();
73 comptime try testNullTerminatedPtr();
74}
75
76fn testNullTerminatedPtr() !void {
77 const ptr_info = @typeInfo([*:0]u8);
78 try expect(ptr_info == .Pointer);
79 try expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
80 try expect(ptr_info.Pointer.is_const == false);
81 try expect(ptr_info.Pointer.is_volatile == false);
82 try expect(ptr_info.Pointer.sentinel.? == 0);
83
84 try expect(@typeInfo([:0]u8).Pointer.sentinel != null);
85}
86
87test "type info: C pointer type info" {
88 try testCPtr();
89 comptime try testCPtr();
90}
91
92fn testCPtr() !void {
93 const ptr_info = @typeInfo([*c]align(4) const i8);
94 try expect(ptr_info == .Pointer);
95 try expect(ptr_info.Pointer.size == .C);
96 try expect(ptr_info.Pointer.is_const);
97 try expect(!ptr_info.Pointer.is_volatile);
98 try expect(ptr_info.Pointer.alignment == 4);
99 try expect(ptr_info.Pointer.child == i8);
100}
101
102test "type info: slice type info" {
103 try testSlice();
104 comptime try testSlice();
105}
106
107fn testSlice() !void {
108 const u32_slice_info = @typeInfo([]u32);
109 try expect(u32_slice_info == .Pointer);
110 try expect(u32_slice_info.Pointer.size == .Slice);
111 try expect(u32_slice_info.Pointer.is_const == false);
112 try expect(u32_slice_info.Pointer.is_volatile == false);
113 try expect(u32_slice_info.Pointer.alignment == 4);
114 try expect(u32_slice_info.Pointer.child == u32);
115}
116
117test "type info: array type info" {
118 try testArray();
119 comptime try testArray();
120}
121
122fn testArray() !void {
123 {
124 const info = @typeInfo([42]u8);
125 try expect(info == .Array);
126 try expect(info.Array.len == 42);
127 try expect(info.Array.child == u8);
128 try expect(info.Array.sentinel == null);
129 }
130
131 {
132 const info = @typeInfo([10:0]u8);
133 try expect(info.Array.len == 10);
134 try expect(info.Array.child == u8);
135 try expect(info.Array.sentinel.? == @as(u8, 0));
136 try expect(@sizeOf([10:0]u8) == info.Array.len + 1);
137 }
138}
139
140test "type info: optional type info" {
141 try testOptional();
142 comptime try testOptional();
143}
144
145fn testOptional() !void {
146 const null_info = @typeInfo(?void);
147 try expect(null_info == .Optional);
148 try expect(null_info.Optional.child == void);
149}
150
151test "type info: error set, error union info" {
152 try testErrorSet();
153 comptime try testErrorSet();
154}
155
156fn testErrorSet() !void {
157 const TestErrorSet = error{
158 First,
159 Second,
160 Third,
161 };
162
163 const error_set_info = @typeInfo(TestErrorSet);
164 try expect(error_set_info == .ErrorSet);
165 try expect(error_set_info.ErrorSet.?.len == 3);
166 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "First"));
167
168 const error_union_info = @typeInfo(TestErrorSet!usize);
169 try expect(error_union_info == .ErrorUnion);
170 try expect(error_union_info.ErrorUnion.error_set == TestErrorSet);
171 try expect(error_union_info.ErrorUnion.payload == usize);
172
173 const global_info = @typeInfo(anyerror);
174 try expect(global_info == .ErrorSet);
175 try expect(global_info.ErrorSet == null);
176}
177
178test "type info: enum info" {
179 try testEnum();
180 comptime try testEnum();
181}
182
183fn testEnum() !void {
184 const Os = enum {
185 Windows,
186 Macos,
187 Linux,
188 FreeBSD,
189 };
190
191 const os_info = @typeInfo(Os);
192 try expect(os_info == .Enum);
193 try expect(os_info.Enum.layout == .Auto);
194 try expect(os_info.Enum.fields.len == 4);
195 try expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
196 try expect(os_info.Enum.fields[3].value == 3);
197 try expect(os_info.Enum.tag_type == u2);
198 try expect(os_info.Enum.decls.len == 0);
199}
200
201test "type info: union info" {
202 try testUnion();
203 comptime try testUnion();
204}
205
206fn testUnion() !void {
207 const typeinfo_info = @typeInfo(TypeInfo);
208 try expect(typeinfo_info == .Union);
209 try expect(typeinfo_info.Union.layout == .Auto);
210 try expect(typeinfo_info.Union.tag_type.? == TypeId);
211 try expect(typeinfo_info.Union.fields.len == 25);
212 try expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
213 try expect(typeinfo_info.Union.decls.len == 22);
214
215 const TestNoTagUnion = union {
216 Foo: void,
217 Bar: u32,
218 };
219
220 const notag_union_info = @typeInfo(TestNoTagUnion);
221 try expect(notag_union_info == .Union);
222 try expect(notag_union_info.Union.tag_type == null);
223 try expect(notag_union_info.Union.layout == .Auto);
224 try expect(notag_union_info.Union.fields.len == 2);
225 try expect(notag_union_info.Union.fields[0].alignment == @alignOf(void));
226 try expect(notag_union_info.Union.fields[1].field_type == u32);
227 try expect(notag_union_info.Union.fields[1].alignment == @alignOf(u32));
228
229 const TestExternUnion = extern union {
230 foo: *c_void,
231 };
232
233 const extern_union_info = @typeInfo(TestExternUnion);
234 try expect(extern_union_info.Union.layout == .Extern);
235 try expect(extern_union_info.Union.tag_type == null);
236 try expect(extern_union_info.Union.fields[0].field_type == *c_void);
237}
238
239test "type info: struct info" {
240 try testStruct();
241 comptime try testStruct();
242}
243
244fn testStruct() !void {
245 const unpacked_struct_info = @typeInfo(TestUnpackedStruct);
246 try expect(unpacked_struct_info.Struct.is_tuple == false);
247 try expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32));
248 try expect(unpacked_struct_info.Struct.fields[0].default_value.? == 4);
249 try expectEqualStrings("foobar", unpacked_struct_info.Struct.fields[1].default_value.?);
250
251 const struct_info = @typeInfo(TestStruct);
252 try expect(struct_info == .Struct);
253 try expect(struct_info.Struct.is_tuple == false);
254 try expect(struct_info.Struct.layout == .Packed);
255 try expect(struct_info.Struct.fields.len == 4);
256 try expect(struct_info.Struct.fields[0].alignment == 2 * @alignOf(usize));
257 try expect(struct_info.Struct.fields[2].field_type == *TestStruct);
258 try expect(struct_info.Struct.fields[2].default_value == null);
259 try expect(struct_info.Struct.fields[3].default_value.? == 4);
260 try expect(struct_info.Struct.fields[3].alignment == 1);
261 try expect(struct_info.Struct.decls.len == 2);
262 try expect(struct_info.Struct.decls[0].is_pub);
263 try expect(!struct_info.Struct.decls[0].data.Fn.is_extern);
264 try expect(struct_info.Struct.decls[0].data.Fn.lib_name == null);
265 try expect(struct_info.Struct.decls[0].data.Fn.return_type == void);
266 try expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void);
267}
268
269const TestUnpackedStruct = struct {
270 fieldA: u32 = 4,
271 fieldB: *const [6:0]u8 = "foobar",
272};
273
274const TestStruct = packed struct {
275 fieldA: usize align(2 * @alignOf(usize)),
276 fieldB: void,
277 fieldC: *Self,
278 fieldD: u32 = 4,
279
280 pub fn foo(self: *const Self) void {}
281 const Self = @This();
282};
283
284test "type info: opaque info" {
285 try testOpaque();
286 comptime try testOpaque();
287}
288
289fn testOpaque() !void {
290 const Foo = opaque {
291 const A = 1;
292 fn b() void {}
293 };
294
295 const foo_info = @typeInfo(Foo);
296 try expect(foo_info.Opaque.decls.len == 2);
297}
298
299test "type info: function type info" {
300 // wasm doesn't support align attributes on functions
301 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
302 try testFunction();
303 comptime try testFunction();
304}
305
306fn testFunction() !void {
307 const fn_info = @typeInfo(@TypeOf(foo));
308 try expect(fn_info == .Fn);
309 try expect(fn_info.Fn.alignment > 0);
310 try expect(fn_info.Fn.calling_convention == .C);
311 try expect(!fn_info.Fn.is_generic);
312 try expect(fn_info.Fn.args.len == 2);
313 try expect(fn_info.Fn.is_var_args);
314 try expect(fn_info.Fn.return_type.? == usize);
315 const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));
316 try expect(fn_aligned_info.Fn.alignment == 4);
317
318 const test_instance: TestStruct = undefined;
319 const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));
320 try expect(bound_fn_info == .BoundFn);
321 try expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
322}
323
324extern fn foo(a: usize, b: bool, ...) callconv(.C) usize;
325extern fn fooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;
326
327test "typeInfo with comptime parameter in struct fn def" {
328 const S = struct {
329 pub fn func(comptime x: f32) void {}
330 };
331 comptime var info = @typeInfo(S);
332}
333
334test "type info: vectors" {
335 try testVector();
336 comptime try testVector();
337}
338
339fn testVector() !void {
340 const vec_info = @typeInfo(std.meta.Vector(4, i32));
341 try expect(vec_info == .Vector);
342 try expect(vec_info.Vector.len == 4);
343 try expect(vec_info.Vector.child == i32);
344}
345
346test "type info: anyframe and anyframe->T" {
347 try testAnyFrame();
348 comptime try testAnyFrame();
349}
350
351fn testAnyFrame() !void {
352 {
353 const anyframe_info = @typeInfo(anyframe->i32);
354 try expect(anyframe_info == .AnyFrame);
355 try expect(anyframe_info.AnyFrame.child.? == i32);
356 }
357
358 {
359 const anyframe_info = @typeInfo(anyframe);
360 try expect(anyframe_info == .AnyFrame);
361 try expect(anyframe_info.AnyFrame.child == null);
362 }
363}
364
365test "type info: pass to function" {
366 _ = passTypeInfo(@typeInfo(void));
367 _ = comptime passTypeInfo(@typeInfo(void));
368}
369
370fn passTypeInfo(comptime info: TypeInfo) type {
371 return void;
372}
373
374test "type info: TypeId -> TypeInfo impl cast" {
375 _ = passTypeInfo(TypeId.Void);
376 _ = comptime passTypeInfo(TypeId.Void);
377}
378
379test "type info: extern fns with and without lib names" {
380 const S = struct {
381 extern fn bar1() void;
382 extern "cool" fn bar2() void;
383 };
384 const info = @typeInfo(S);
385 comptime {
386 for (info.Struct.decls) |decl| {
387 if (std.mem.eql(u8, decl.name, "bar1")) {
388 try expect(decl.data.Fn.lib_name == null);
389 } else {
390 try expectEqualStrings("cool", decl.data.Fn.lib_name.?);
391 }
392 }
393 }
394}
395
396test "data field is a compile-time value" {
397 const S = struct {
398 const Bar = @as(isize, -1);
399 };
400 comptime try expect(@typeInfo(S).Struct.decls[0].data.Var == isize);
401}
402
403test "sentinel of opaque pointer type" {
404 const c_void_info = @typeInfo(*c_void);
405 try expect(c_void_info.Pointer.sentinel == null);
406}
407
408test "@typeInfo does not force declarations into existence" {
409 const S = struct {
410 x: i32,
411
412 fn doNotReferenceMe() void {
413 @compileError("test failed");
414 }
415 };
416 comptime try expect(@typeInfo(S).Struct.fields.len == 1);
417}
418
419test "defaut value for a var-typed field" {
420 const S = struct { x: anytype };
421 try expect(@typeInfo(S).Struct.fields[0].default_value == null);
422}
423
424fn add(a: i32, b: i32) i32 {
425 return a + b;
426}
427
428test "type info for async frames" {
429 switch (@typeInfo(@Frame(add))) {
430 .Frame => |frame| {
431 try expect(frame.function == add);
432 },
433 else => unreachable,
434 }
435}
436
437test "type info: value is correctly copied" {
438 comptime {
439 var ptrInfo = @typeInfo([]u32);
440 ptrInfo.Pointer.size = .One;
441 try expect(@typeInfo([]u32).Pointer.size == .Slice);
442 }
443}
444
445test "Declarations are returned in declaration order" {
446 const S = struct {
447 const a = 1;
448 const b = 2;
449 const c = 3;
450 const d = 4;
451 const e = 5;
452 };
453 const d = @typeInfo(S).Struct.decls;
454 try expect(std.mem.eql(u8, d[0].name, "a"));
455 try expect(std.mem.eql(u8, d[1].name, "b"));
456 try expect(std.mem.eql(u8, d[2].name, "c"));
457 try expect(std.mem.eql(u8, d[3].name, "d"));
458 try expect(std.mem.eql(u8, d[4].name, "e"));
459}
460
461test "Struct.is_tuple" {
462 try expect(@typeInfo(@TypeOf(.{0})).Struct.is_tuple);
463 try expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);
464}
465
466test "StructField.is_comptime" {
467 const info = @typeInfo(struct { x: u8 = 3, comptime y: u32 = 5 }).Struct;
468 try expect(!info.fields[0].is_comptime);
469 try expect(info.fields[1].is_comptime);
470}
471
472test "typeInfo resolves usingnamespace declarations" {
473 const A = struct {
474 pub const f1 = 42;
475 };
476
477 const B = struct {
478 const f0 = 42;
479 usingnamespace A;
480 };
481
482 try expect(@typeInfo(B).Struct.decls.len == 2);
483 //a
484}
test/behavior/typename.zig created+7
...@@ -0,0 +1,7 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
4
5test "slice" {
6 try expectEqualSlices(u8, "[]u8", @typeName([]u8));
7}
test/behavior/undefined.zig created+69
...@@ -0,0 +1,69 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4
5fn initStaticArray() [10]i32 {
6 var array: [10]i32 = undefined;
7 array[0] = 1;
8 array[4] = 2;
9 array[7] = 3;
10 array[9] = 4;
11 return array;
12}
13const static_array = initStaticArray();
14test "init static array to undefined" {
15 try expect(static_array[0] == 1);
16 try expect(static_array[4] == 2);
17 try expect(static_array[7] == 3);
18 try expect(static_array[9] == 4);
19
20 comptime {
21 try expect(static_array[0] == 1);
22 try expect(static_array[4] == 2);
23 try expect(static_array[7] == 3);
24 try expect(static_array[9] == 4);
25 }
26}
27
28const Foo = struct {
29 x: i32,
30
31 fn setFooXMethod(foo: *Foo) void {
32 foo.x = 3;
33 }
34};
35
36fn setFooX(foo: *Foo) void {
37 foo.x = 2;
38}
39
40test "assign undefined to struct" {
41 comptime {
42 var foo: Foo = undefined;
43 setFooX(&foo);
44 try expect(foo.x == 2);
45 }
46 {
47 var foo: Foo = undefined;
48 setFooX(&foo);
49 try expect(foo.x == 2);
50 }
51}
52
53test "assign undefined to struct with method" {
54 comptime {
55 var foo: Foo = undefined;
56 foo.setFooXMethod();
57 try expect(foo.x == 3);
58 }
59 {
60 var foo: Foo = undefined;
61 foo.setFooXMethod();
62 try expect(foo.x == 3);
63 }
64}
65
66test "type name of undefined" {
67 const x = undefined;
68 try expect(mem.eql(u8, @typeName(@TypeOf(x)), "(undefined)"));
69}
test/behavior/underscore.zig created+28
...@@ -0,0 +1,28 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "ignore lval with underscore" {
5 _ = false;
6}
7
8test "ignore lval with underscore (for loop)" {
9 for ([_]void{}) |_, i| {
10 for ([_]void{}) |_, j| {
11 break;
12 }
13 break;
14 }
15}
16
17test "ignore lval with underscore (while loop)" {
18 while (optionalReturnError()) |_| {
19 while (optionalReturnError()) |_| {
20 break;
21 } else |_| {}
22 break;
23 } else |_| {}
24}
25
26fn optionalReturnError() !?u32 {
27 return error.optionalReturnError;
28}
test/behavior/union.zig created+806
...@@ -0,0 +1,806 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const Tag = std.meta.Tag;
5
6const Value = union(enum) {
7 Int: u64,
8 Array: [9]u8,
9};
10
11const Agg = struct {
12 val1: Value,
13 val2: Value,
14};
15
16const v1 = Value{ .Int = 1234 };
17const v2 = Value{ .Array = [_]u8{3} ** 9 };
18
19const err = @as(anyerror!Agg, Agg{
20 .val1 = v1,
21 .val2 = v2,
22});
23
24const array = [_]Value{
25 v1,
26 v2,
27 v1,
28 v2,
29};
30
31test "unions embedded in aggregate types" {
32 switch (array[1]) {
33 Value.Array => |arr| try expect(arr[4] == 3),
34 else => unreachable,
35 }
36 switch ((err catch unreachable).val1) {
37 Value.Int => |x| try expect(x == 1234),
38 else => unreachable,
39 }
40}
41
42const Foo = union {
43 float: f64,
44 int: i32,
45};
46
47test "basic unions" {
48 var foo = Foo{ .int = 1 };
49 try expect(foo.int == 1);
50 foo = Foo{ .float = 12.34 };
51 try expect(foo.float == 12.34);
52}
53
54test "comptime union field access" {
55 comptime {
56 var foo = Foo{ .int = 0 };
57 try expect(foo.int == 0);
58
59 foo = Foo{ .float = 42.42 };
60 try expect(foo.float == 42.42);
61 }
62}
63
64test "init union with runtime value" {
65 var foo: Foo = undefined;
66
67 setFloat(&foo, 12.34);
68 try expect(foo.float == 12.34);
69
70 setInt(&foo, 42);
71 try expect(foo.int == 42);
72}
73
74fn setFloat(foo: *Foo, x: f64) void {
75 foo.* = Foo{ .float = x };
76}
77
78fn setInt(foo: *Foo, x: i32) void {
79 foo.* = Foo{ .int = x };
80}
81
82const FooExtern = extern union {
83 float: f64,
84 int: i32,
85};
86
87test "basic extern unions" {
88 var foo = FooExtern{ .int = 1 };
89 try expect(foo.int == 1);
90 foo.float = 12.34;
91 try expect(foo.float == 12.34);
92}
93
94const Letter = enum {
95 A,
96 B,
97 C,
98};
99const Payload = union(Letter) {
100 A: i32,
101 B: f64,
102 C: bool,
103};
104
105test "union with specified enum tag" {
106 try doTest();
107 comptime try doTest();
108}
109
110fn doTest() !void {
111 try expect((try bar(Payload{ .A = 1234 })) == -10);
112}
113
114fn bar(value: Payload) !i32 {
115 try expect(@as(Letter, value) == Letter.A);
116 return switch (value) {
117 Payload.A => |x| return x - 1244,
118 Payload.B => |x| if (x == 12.34) @as(i32, 20) else 21,
119 Payload.C => |x| if (x) @as(i32, 30) else 31,
120 };
121}
122
123const MultipleChoice = union(enum(u32)) {
124 A = 20,
125 B = 40,
126 C = 60,
127 D = 1000,
128};
129test "simple union(enum(u32))" {
130 var x = MultipleChoice.C;
131 try expect(x == MultipleChoice.C);
132 try expect(@enumToInt(@as(Tag(MultipleChoice), x)) == 60);
133}
134
135const MultipleChoice2 = union(enum(u32)) {
136 Unspecified1: i32,
137 A: f32 = 20,
138 Unspecified2: void,
139 B: bool = 40,
140 Unspecified3: i32,
141 C: i8 = 60,
142 Unspecified4: void,
143 D: void = 1000,
144 Unspecified5: i32,
145};
146
147test "union(enum(u32)) with specified and unspecified tag values" {
148 comptime try expect(Tag(Tag(MultipleChoice2)) == u32);
149 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
150 comptime try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
151}
152
153fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void {
154 try expect(@enumToInt(@as(Tag(MultipleChoice2), x)) == 60);
155 try expect(1123 == switch (x) {
156 MultipleChoice2.A => 1,
157 MultipleChoice2.B => 2,
158 MultipleChoice2.C => |v| @as(i32, 1000) + v,
159 MultipleChoice2.D => 4,
160 MultipleChoice2.Unspecified1 => 5,
161 MultipleChoice2.Unspecified2 => 6,
162 MultipleChoice2.Unspecified3 => 7,
163 MultipleChoice2.Unspecified4 => 8,
164 MultipleChoice2.Unspecified5 => 9,
165 });
166}
167
168const ExternPtrOrInt = extern union {
169 ptr: *u8,
170 int: u64,
171};
172test "extern union size" {
173 comptime try expect(@sizeOf(ExternPtrOrInt) == 8);
174}
175
176const PackedPtrOrInt = packed union {
177 ptr: *u8,
178 int: u64,
179};
180test "extern union size" {
181 comptime try expect(@sizeOf(PackedPtrOrInt) == 8);
182}
183
184const ZeroBits = union {
185 OnlyField: void,
186};
187test "union with only 1 field which is void should be zero bits" {
188 comptime try expect(@sizeOf(ZeroBits) == 0);
189}
190
191const TheTag = enum {
192 A,
193 B,
194 C,
195};
196const TheUnion = union(TheTag) {
197 A: i32,
198 B: i32,
199 C: i32,
200};
201test "union field access gives the enum values" {
202 try expect(TheUnion.A == TheTag.A);
203 try expect(TheUnion.B == TheTag.B);
204 try expect(TheUnion.C == TheTag.C);
205}
206
207test "cast union to tag type of union" {
208 try testCastUnionToTag(TheUnion{ .B = 1234 });
209 comptime try testCastUnionToTag(TheUnion{ .B = 1234 });
210}
211
212fn testCastUnionToTag(x: TheUnion) !void {
213 try expect(@as(TheTag, x) == TheTag.B);
214}
215
216test "cast tag type of union to union" {
217 var x: Value2 = Letter2.B;
218 try expect(@as(Letter2, x) == Letter2.B);
219}
220const Letter2 = enum {
221 A,
222 B,
223 C,
224};
225const Value2 = union(Letter2) {
226 A: i32,
227 B,
228 C,
229};
230
231test "implicit cast union to its tag type" {
232 var x: Value2 = Letter2.B;
233 try expect(x == Letter2.B);
234 try giveMeLetterB(x);
235}
236fn giveMeLetterB(x: Letter2) !void {
237 try expect(x == Value2.B);
238}
239
240pub const PackThis = union(enum) {
241 Invalid: bool,
242 StringLiteral: u2,
243};
244
245test "constant packed union" {
246 try testConstPackedUnion(&[_]PackThis{PackThis{ .StringLiteral = 1 }});
247}
248
249fn testConstPackedUnion(expected_tokens: []const PackThis) !void {
250 try expect(expected_tokens[0].StringLiteral == 1);
251}
252
253test "switch on union with only 1 field" {
254 var r: PartialInst = undefined;
255 r = PartialInst.Compiled;
256 switch (r) {
257 PartialInst.Compiled => {
258 var z: PartialInstWithPayload = undefined;
259 z = PartialInstWithPayload{ .Compiled = 1234 };
260 switch (z) {
261 PartialInstWithPayload.Compiled => |x| {
262 try expect(x == 1234);
263 return;
264 },
265 }
266 },
267 }
268 unreachable;
269}
270
271const PartialInst = union(enum) {
272 Compiled,
273};
274
275const PartialInstWithPayload = union(enum) {
276 Compiled: i32,
277};
278
279test "access a member of tagged union with conflicting enum tag name" {
280 const Bar = union(enum) {
281 A: A,
282 B: B,
283
284 const A = u8;
285 const B = void;
286 };
287
288 comptime try expect(Bar.A == u8);
289}
290
291test "tagged union initialization with runtime void" {
292 try expect(testTaggedUnionInit({}));
293}
294
295const TaggedUnionWithAVoid = union(enum) {
296 A,
297 B: i32,
298};
299
300fn testTaggedUnionInit(x: anytype) bool {
301 const y = TaggedUnionWithAVoid{ .A = x };
302 return @as(Tag(TaggedUnionWithAVoid), y) == TaggedUnionWithAVoid.A;
303}
304
305pub const UnionEnumNoPayloads = union(enum) {
306 A,
307 B,
308};
309
310test "tagged union with no payloads" {
311 const a = UnionEnumNoPayloads{ .B = {} };
312 switch (a) {
313 Tag(UnionEnumNoPayloads).A => @panic("wrong"),
314 Tag(UnionEnumNoPayloads).B => {},
315 }
316}
317
318test "union with only 1 field casted to its enum type" {
319 const Literal = union(enum) {
320 Number: f64,
321 Bool: bool,
322 };
323
324 const Expr = union(enum) {
325 Literal: Literal,
326 };
327
328 var e = Expr{ .Literal = Literal{ .Bool = true } };
329 const ExprTag = Tag(Expr);
330 comptime try expect(Tag(ExprTag) == u0);
331 var t = @as(ExprTag, e);
332 try expect(t == Expr.Literal);
333}
334
335test "union with only 1 field casted to its enum type which has enum value specified" {
336 const Literal = union(enum) {
337 Number: f64,
338 Bool: bool,
339 };
340
341 const ExprTag = enum(comptime_int) {
342 Literal = 33,
343 };
344
345 const Expr = union(ExprTag) {
346 Literal: Literal,
347 };
348
349 var e = Expr{ .Literal = Literal{ .Bool = true } };
350 comptime try expect(Tag(ExprTag) == comptime_int);
351 var t = @as(ExprTag, e);
352 try expect(t == Expr.Literal);
353 try expect(@enumToInt(t) == 33);
354 comptime try expect(@enumToInt(t) == 33);
355}
356
357test "@enumToInt works on unions" {
358 const Bar = union(enum) {
359 A: bool,
360 B: u8,
361 C,
362 };
363
364 const a = Bar{ .A = true };
365 var b = Bar{ .B = undefined };
366 var c = Bar.C;
367 try expect(@enumToInt(a) == 0);
368 try expect(@enumToInt(b) == 1);
369 try expect(@enumToInt(c) == 2);
370}
371
372const Attribute = union(enum) {
373 A: bool,
374 B: u8,
375};
376
377fn setAttribute(attr: Attribute) void {}
378
379fn Setter(attr: Attribute) type {
380 return struct {
381 fn set() void {
382 setAttribute(attr);
383 }
384 };
385}
386
387test "comptime union field value equality" {
388 const a0 = Setter(Attribute{ .A = false });
389 const a1 = Setter(Attribute{ .A = true });
390 const a2 = Setter(Attribute{ .A = false });
391
392 const b0 = Setter(Attribute{ .B = 5 });
393 const b1 = Setter(Attribute{ .B = 9 });
394 const b2 = Setter(Attribute{ .B = 5 });
395
396 try expect(a0 == a0);
397 try expect(a1 == a1);
398 try expect(a0 == a2);
399
400 try expect(b0 == b0);
401 try expect(b1 == b1);
402 try expect(b0 == b2);
403
404 try expect(a0 != b0);
405 try expect(a0 != a1);
406 try expect(b0 != b1);
407}
408
409test "return union init with void payload" {
410 const S = struct {
411 fn entry() !void {
412 try expect(func().state == State.one);
413 }
414 const Outer = union(enum) {
415 state: State,
416 };
417 const State = union(enum) {
418 one: void,
419 two: u32,
420 };
421 fn func() Outer {
422 return Outer{ .state = State{ .one = {} } };
423 }
424 };
425 try S.entry();
426 comptime try S.entry();
427}
428
429test "@unionInit can modify a union type" {
430 const UnionInitEnum = union(enum) {
431 Boolean: bool,
432 Byte: u8,
433 };
434
435 var value: UnionInitEnum = undefined;
436
437 value = @unionInit(UnionInitEnum, "Boolean", true);
438 try expect(value.Boolean == true);
439 value.Boolean = false;
440 try expect(value.Boolean == false);
441
442 value = @unionInit(UnionInitEnum, "Byte", 2);
443 try expect(value.Byte == 2);
444 value.Byte = 3;
445 try expect(value.Byte == 3);
446}
447
448test "@unionInit can modify a pointer value" {
449 const UnionInitEnum = union(enum) {
450 Boolean: bool,
451 Byte: u8,
452 };
453
454 var value: UnionInitEnum = undefined;
455 var value_ptr = &value;
456
457 value_ptr.* = @unionInit(UnionInitEnum, "Boolean", true);
458 try expect(value.Boolean == true);
459
460 value_ptr.* = @unionInit(UnionInitEnum, "Byte", 2);
461 try expect(value.Byte == 2);
462}
463
464test "union no tag with struct member" {
465 const Struct = struct {};
466 const Union = union {
467 s: Struct,
468 pub fn foo(self: *@This()) void {}
469 };
470 var u = Union{ .s = Struct{} };
471 u.foo();
472}
473
474fn testComparison() !void {
475 var x = Payload{ .A = 42 };
476 try expect(x == .A);
477 try expect(x != .B);
478 try expect(x != .C);
479 try expect((x == .B) == false);
480 try expect((x == .C) == false);
481 try expect((x != .A) == false);
482}
483
484test "comparison between union and enum literal" {
485 try testComparison();
486 comptime try testComparison();
487}
488
489test "packed union generates correctly aligned LLVM type" {
490 const U = packed union {
491 f1: fn () error{TestUnexpectedResult}!void,
492 f2: u32,
493 };
494 var foo = [_]U{
495 U{ .f1 = doTest },
496 U{ .f2 = 0 },
497 };
498 try foo[0].f1();
499}
500
501test "union with one member defaults to u0 tag type" {
502 const U0 = union(enum) {
503 X: u32,
504 };
505 comptime try expect(Tag(Tag(U0)) == u0);
506}
507
508test "union with comptime_int tag" {
509 const Union = union(enum(comptime_int)) {
510 X: u32,
511 Y: u16,
512 Z: u8,
513 };
514 comptime try expect(Tag(Tag(Union)) == comptime_int);
515}
516
517test "extern union doesn't trigger field check at comptime" {
518 const U = extern union {
519 x: u32,
520 y: u8,
521 };
522
523 const x = U{ .x = 0x55AAAA55 };
524 comptime try expect(x.y == 0x55);
525}
526
527const Foo1 = union(enum) {
528 f: struct {
529 x: usize,
530 },
531};
532var glbl: Foo1 = undefined;
533
534test "global union with single field is correctly initialized" {
535 glbl = Foo1{
536 .f = @typeInfo(Foo1).Union.fields[0].field_type{ .x = 123 },
537 };
538 try expect(glbl.f.x == 123);
539}
540
541pub const FooUnion = union(enum) {
542 U0: usize,
543 U1: u8,
544};
545
546var glbl_array: [2]FooUnion = undefined;
547
548test "initialize global array of union" {
549 glbl_array[1] = FooUnion{ .U1 = 2 };
550 glbl_array[0] = FooUnion{ .U0 = 1 };
551 try expect(glbl_array[0].U0 == 1);
552 try expect(glbl_array[1].U1 == 2);
553}
554
555test "anonymous union literal syntax" {
556 const S = struct {
557 const Number = union {
558 int: i32,
559 float: f64,
560 };
561
562 fn doTheTest() !void {
563 var i: Number = .{ .int = 42 };
564 var f = makeNumber();
565 try expect(i.int == 42);
566 try expect(f.float == 12.34);
567 }
568
569 fn makeNumber() Number {
570 return .{ .float = 12.34 };
571 }
572 };
573 try S.doTheTest();
574 comptime try S.doTheTest();
575}
576
577test "update the tag value for zero-sized unions" {
578 const S = union(enum) {
579 U0: void,
580 U1: void,
581 };
582 var x = S{ .U0 = {} };
583 try expect(x == .U0);
584 x = S{ .U1 = {} };
585 try expect(x == .U1);
586}
587
588test "function call result coerces from tagged union to the tag" {
589 const S = struct {
590 const Arch = union(enum) {
591 One,
592 Two: usize,
593 };
594
595 const ArchTag = Tag(Arch);
596
597 fn doTheTest() !void {
598 var x: ArchTag = getArch1();
599 try expect(x == .One);
600
601 var y: ArchTag = getArch2();
602 try expect(y == .Two);
603 }
604
605 pub fn getArch1() Arch {
606 return .One;
607 }
608
609 pub fn getArch2() Arch {
610 return .{ .Two = 99 };
611 }
612 };
613 try S.doTheTest();
614 comptime try S.doTheTest();
615}
616
617test "0-sized extern union definition" {
618 const U = extern union {
619 a: void,
620 const f = 1;
621 };
622
623 try expect(U.f == 1);
624}
625
626test "union initializer generates padding only if needed" {
627 const U = union(enum) {
628 A: u24,
629 };
630
631 var v = U{ .A = 532 };
632 try expect(v.A == 532);
633}
634
635test "runtime tag name with single field" {
636 const U = union(enum) {
637 A: i32,
638 };
639
640 var v = U{ .A = 42 };
641 try expect(std.mem.eql(u8, @tagName(v), "A"));
642}
643
644test "cast from anonymous struct to union" {
645 const S = struct {
646 const U = union(enum) {
647 A: u32,
648 B: []const u8,
649 C: void,
650 };
651 fn doTheTest() !void {
652 var y: u32 = 42;
653 const t0 = .{ .A = 123 };
654 const t1 = .{ .B = "foo" };
655 const t2 = .{ .C = {} };
656 const t3 = .{ .A = y };
657 const x0: U = t0;
658 var x1: U = t1;
659 const x2: U = t2;
660 var x3: U = t3;
661 try expect(x0.A == 123);
662 try expect(std.mem.eql(u8, x1.B, "foo"));
663 try expect(x2 == .C);
664 try expect(x3.A == y);
665 }
666 };
667 try S.doTheTest();
668 comptime try S.doTheTest();
669}
670
671test "cast from pointer to anonymous struct to pointer to union" {
672 const S = struct {
673 const U = union(enum) {
674 A: u32,
675 B: []const u8,
676 C: void,
677 };
678 fn doTheTest() !void {
679 var y: u32 = 42;
680 const t0 = &.{ .A = 123 };
681 const t1 = &.{ .B = "foo" };
682 const t2 = &.{ .C = {} };
683 const t3 = &.{ .A = y };
684 const x0: *const U = t0;
685 var x1: *const U = t1;
686 const x2: *const U = t2;
687 var x3: *const U = t3;
688 try expect(x0.A == 123);
689 try expect(std.mem.eql(u8, x1.B, "foo"));
690 try expect(x2.* == .C);
691 try expect(x3.A == y);
692 }
693 };
694 try S.doTheTest();
695 comptime try S.doTheTest();
696}
697
698test "method call on an empty union" {
699 const S = struct {
700 const MyUnion = union(MyUnionTag) {
701 pub const MyUnionTag = enum { X1, X2 };
702 X1: [0]u8,
703 X2: [0]u8,
704
705 pub fn useIt(self: *@This()) bool {
706 return true;
707 }
708 };
709
710 fn doTheTest() !void {
711 var u = MyUnion{ .X1 = [0]u8{} };
712 try expect(u.useIt());
713 }
714 };
715 try S.doTheTest();
716 comptime try S.doTheTest();
717}
718
719test "switching on non exhaustive union" {
720 const S = struct {
721 const E = enum(u8) {
722 a,
723 b,
724 _,
725 };
726 const U = union(E) {
727 a: i32,
728 b: u32,
729 };
730 fn doTheTest() !void {
731 var a = U{ .a = 2 };
732 switch (a) {
733 .a => |val| try expect(val == 2),
734 .b => unreachable,
735 }
736 }
737 };
738 try S.doTheTest();
739 comptime try S.doTheTest();
740}
741
742test "containers with single-field enums" {
743 const S = struct {
744 const A = union(enum) { f1 };
745 const B = union(enum) { f1: void };
746 const C = struct { a: A };
747 const D = struct { a: B };
748
749 fn doTheTest() !void {
750 var array1 = [1]A{A{ .f1 = {} }};
751 var array2 = [1]B{B{ .f1 = {} }};
752 try expect(array1[0] == .f1);
753 try expect(array2[0] == .f1);
754
755 var struct1 = C{ .a = A{ .f1 = {} } };
756 var struct2 = D{ .a = B{ .f1 = {} } };
757 try expect(struct1.a == .f1);
758 try expect(struct2.a == .f1);
759 }
760 };
761
762 try S.doTheTest();
763 comptime try S.doTheTest();
764}
765
766test "@unionInit on union w/ tag but no fields" {
767 const S = struct {
768 const Type = enum(u8) { no_op = 105 };
769
770 const Data = union(Type) {
771 no_op: void,
772
773 pub fn decode(buf: []const u8) Data {
774 return @unionInit(Data, "no_op", {});
775 }
776 };
777
778 comptime {
779 try expect(@sizeOf(Data) != 0);
780 }
781
782 fn doTheTest() !void {
783 var data: Data = .{ .no_op = .{} };
784 var o = Data.decode(&[_]u8{});
785 try expectEqual(Type.no_op, o);
786 }
787 };
788
789 try S.doTheTest();
790 comptime try S.doTheTest();
791}
792
793test "union enum type gets a separate scope" {
794 const S = struct {
795 const U = union(enum) {
796 a: u8,
797 const foo = 1;
798 };
799
800 fn doTheTest() !void {
801 try expect(!@hasDecl(Tag(U), "foo"));
802 }
803 };
804
805 try S.doTheTest();
806}
test/behavior/usingnamespace.zig created+22
...@@ -0,0 +1,22 @@
1const std = @import("std");
2
3fn Foo(comptime T: type) type {
4 return struct {
5 usingnamespace T;
6 };
7}
8
9test "usingnamespace inside a generic struct" {
10 const std2 = Foo(std);
11 const testing2 = Foo(std.testing);
12 try std2.testing.expect(true);
13 try testing2.expect(true);
14}
15
16usingnamespace struct {
17 pub const foo = 42;
18};
19
20test "usingnamespace does not redeclare an imported variable" {
21 comptime try std.testing.expect(foo == 42);
22}
test/behavior/var_args.zig created+83
...@@ -0,0 +1,83 @@
1const expect = @import("std").testing.expect;
2
3fn add(args: anytype) i32 {
4 var sum = @as(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 try expect(add(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
16 try expect(add(.{@as(i32, 1234)}) == 1234);
17 try expect(add(.{}) == 0);
18}
19
20fn readFirstVarArg(args: anytype) void {
21 const value = args[0];
22}
23
24test "send void arg to var args" {
25 readFirstVarArg(.{{}});
26}
27
28test "pass args directly" {
29 try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
30 try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234);
31 try expect(addSomeStuff(.{}) == 0);
32}
33
34fn addSomeStuff(args: anytype) i32 {
35 return add(args);
36}
37
38test "runtime parameter before var args" {
39 try expect((try extraFn(10, .{})) == 0);
40 try expect((try extraFn(10, .{false})) == 1);
41 try expect((try extraFn(10, .{ false, true })) == 2);
42
43 comptime {
44 try expect((try extraFn(10, .{})) == 0);
45 try expect((try extraFn(10, .{false})) == 1);
46 try expect((try extraFn(10, .{ false, true })) == 2);
47 }
48}
49
50fn extraFn(extra: u32, args: anytype) !usize {
51 if (args.len >= 1) {
52 try expect(args[0] == false);
53 }
54 if (args.len >= 2) {
55 try expect(args[1] == true);
56 }
57 return args.len;
58}
59
60const foos = [_]fn (anytype) bool{
61 foo1,
62 foo2,
63};
64
65fn foo1(args: anytype) bool {
66 return true;
67}
68fn foo2(args: anytype) bool {
69 return false;
70}
71
72test "array of var args functions" {
73 try expect(foos[0](.{}));
74 try expect(!foos[1](.{}));
75}
76
77test "pass zero length array to var args param" {
78 doNothingWithFirstArg(.{""});
79}
80
81fn doNothingWithFirstArg(args: anytype) void {
82 const a = args[0];
83}
test/behavior/vector.zig created+640
...@@ -0,0 +1,640 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const mem = std.mem;
4const math = std.math;
5const expect = std.testing.expect;
6const expectEqual = std.testing.expectEqual;
7const expectApproxEqRel = std.testing.expectApproxEqRel;
8const Vector = std.meta.Vector;
9
10test "implicit cast vector to array - bool" {
11 const S = struct {
12 fn doTheTest() !void {
13 const a: Vector(4, bool) = [_]bool{ true, false, true, false };
14 const result_array: [4]bool = a;
15 try expect(mem.eql(bool, &result_array, &[4]bool{ true, false, true, false }));
16 }
17 };
18 try S.doTheTest();
19 comptime try S.doTheTest();
20}
21
22test "vector wrap operators" {
23 const S = struct {
24 fn doTheTest() !void {
25 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
26 var x: Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
27 try expect(mem.eql(i32, &@as([4]i32, v +% x), &[4]i32{ -2147483648, 2147483645, 33, 44 }));
28 try expect(mem.eql(i32, &@as([4]i32, v -% x), &[4]i32{ 2147483646, 2147483647, 27, 36 }));
29 try expect(mem.eql(i32, &@as([4]i32, v *% x), &[4]i32{ 2147483647, 2, 90, 160 }));
30 var z: Vector(4, i32) = [4]i32{ 1, 2, 3, -2147483648 };
31 try expect(mem.eql(i32, &@as([4]i32, -%z), &[4]i32{ -1, -2, -3, -2147483648 }));
32 }
33 };
34 try S.doTheTest();
35 comptime try S.doTheTest();
36}
37
38test "vector bin compares with mem.eql" {
39 const S = struct {
40 fn doTheTest() !void {
41 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
42 var x: Vector(4, i32) = [4]i32{ 1, 2147483647, 30, 4 };
43 try expect(mem.eql(bool, &@as([4]bool, v == x), &[4]bool{ false, false, true, false }));
44 try expect(mem.eql(bool, &@as([4]bool, v != x), &[4]bool{ true, true, false, true }));
45 try expect(mem.eql(bool, &@as([4]bool, v < x), &[4]bool{ false, true, false, false }));
46 try expect(mem.eql(bool, &@as([4]bool, v > x), &[4]bool{ true, false, false, true }));
47 try expect(mem.eql(bool, &@as([4]bool, v <= x), &[4]bool{ false, true, true, false }));
48 try expect(mem.eql(bool, &@as([4]bool, v >= x), &[4]bool{ true, false, true, true }));
49 }
50 };
51 try S.doTheTest();
52 comptime try S.doTheTest();
53}
54
55test "vector int operators" {
56 const S = struct {
57 fn doTheTest() !void {
58 var v: Vector(4, i32) = [4]i32{ 10, 20, 30, 40 };
59 var x: Vector(4, i32) = [4]i32{ 1, 2, 3, 4 };
60 try expect(mem.eql(i32, &@as([4]i32, v + x), &[4]i32{ 11, 22, 33, 44 }));
61 try expect(mem.eql(i32, &@as([4]i32, v - x), &[4]i32{ 9, 18, 27, 36 }));
62 try expect(mem.eql(i32, &@as([4]i32, v * x), &[4]i32{ 10, 40, 90, 160 }));
63 try expect(mem.eql(i32, &@as([4]i32, -v), &[4]i32{ -10, -20, -30, -40 }));
64 }
65 };
66 try S.doTheTest();
67 comptime try S.doTheTest();
68}
69
70test "vector float operators" {
71 const S = struct {
72 fn doTheTest() !void {
73 var v: Vector(4, f32) = [4]f32{ 10, 20, 30, 40 };
74 var x: Vector(4, f32) = [4]f32{ 1, 2, 3, 4 };
75 try expect(mem.eql(f32, &@as([4]f32, v + x), &[4]f32{ 11, 22, 33, 44 }));
76 try expect(mem.eql(f32, &@as([4]f32, v - x), &[4]f32{ 9, 18, 27, 36 }));
77 try expect(mem.eql(f32, &@as([4]f32, v * x), &[4]f32{ 10, 40, 90, 160 }));
78 try expect(mem.eql(f32, &@as([4]f32, -x), &[4]f32{ -1, -2, -3, -4 }));
79 }
80 };
81 try S.doTheTest();
82 comptime try S.doTheTest();
83}
84
85test "vector bit operators" {
86 const S = struct {
87 fn doTheTest() !void {
88 var v: Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 };
89 var x: Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 };
90 try expect(mem.eql(u8, &@as([4]u8, v ^ x), &[4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 }));
91 try expect(mem.eql(u8, &@as([4]u8, v | x), &[4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 }));
92 try expect(mem.eql(u8, &@as([4]u8, v & x), &[4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 }));
93 }
94 };
95 try S.doTheTest();
96 comptime try S.doTheTest();
97}
98
99test "implicit cast vector to array" {
100 const S = struct {
101 fn doTheTest() !void {
102 var a: Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };
103 var result_array: [4]i32 = a;
104 result_array = a;
105 try expect(mem.eql(i32, &result_array, &[4]i32{ 1, 2, 3, 4 }));
106 }
107 };
108 try S.doTheTest();
109 comptime try S.doTheTest();
110}
111
112test "array to vector" {
113 var foo: f32 = 3.14;
114 var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };
115 var vec: Vector(4, f32) = arr;
116}
117
118test "vector casts of sizes not divisable by 8" {
119 // https://github.com/ziglang/zig/issues/3563
120 if (std.Target.current.os.tag == .dragonfly) return error.SkipZigTest;
121
122 const S = struct {
123 fn doTheTest() !void {
124 {
125 var v: Vector(4, u3) = [4]u3{ 5, 2, 3, 0 };
126 var x: [4]u3 = v;
127 try expect(mem.eql(u3, &x, &@as([4]u3, v)));
128 }
129 {
130 var v: Vector(4, u2) = [4]u2{ 1, 2, 3, 0 };
131 var x: [4]u2 = v;
132 try expect(mem.eql(u2, &x, &@as([4]u2, v)));
133 }
134 {
135 var v: Vector(4, u1) = [4]u1{ 1, 0, 1, 0 };
136 var x: [4]u1 = v;
137 try expect(mem.eql(u1, &x, &@as([4]u1, v)));
138 }
139 {
140 var v: Vector(4, bool) = [4]bool{ false, false, true, false };
141 var x: [4]bool = v;
142 try expect(mem.eql(bool, &x, &@as([4]bool, v)));
143 }
144 }
145 };
146 try S.doTheTest();
147 comptime try S.doTheTest();
148}
149
150test "vector @splat" {
151 const S = struct {
152 fn testForT(comptime N: comptime_int, v: anytype) !void {
153 const T = @TypeOf(v);
154 var vec = @splat(N, v);
155 try expectEqual(Vector(N, T), @TypeOf(vec));
156 var as_array = @as([N]T, vec);
157 for (as_array) |elem| try expectEqual(v, elem);
158 }
159 fn doTheTest() !void {
160 // Splats with multiple-of-8 bit types that fill a 128bit vector.
161 try testForT(16, @as(u8, 0xEE));
162 try testForT(8, @as(u16, 0xBEEF));
163 try testForT(4, @as(u32, 0xDEADBEEF));
164 try testForT(2, @as(u64, 0xCAFEF00DDEADBEEF));
165
166 try testForT(8, @as(f16, 3.1415));
167 try testForT(4, @as(f32, 3.1415));
168 try testForT(2, @as(f64, 3.1415));
169
170 // Same but fill more than 128 bits.
171 try testForT(16 * 2, @as(u8, 0xEE));
172 try testForT(8 * 2, @as(u16, 0xBEEF));
173 try testForT(4 * 2, @as(u32, 0xDEADBEEF));
174 try testForT(2 * 2, @as(u64, 0xCAFEF00DDEADBEEF));
175
176 try testForT(8 * 2, @as(f16, 3.1415));
177 try testForT(4 * 2, @as(f32, 3.1415));
178 try testForT(2 * 2, @as(f64, 3.1415));
179 }
180 };
181 try S.doTheTest();
182 comptime try S.doTheTest();
183}
184
185test "load vector elements via comptime index" {
186 const S = struct {
187 fn doTheTest() !void {
188 var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
189 try expect(v[0] == 1);
190 try expect(v[1] == 2);
191 try expect(loadv(&v[2]) == 3);
192 }
193 fn loadv(ptr: anytype) i32 {
194 return ptr.*;
195 }
196 };
197
198 try S.doTheTest();
199 comptime try S.doTheTest();
200}
201
202test "store vector elements via comptime index" {
203 const S = struct {
204 fn doTheTest() !void {
205 var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
206
207 v[2] = 42;
208 try expect(v[1] == 5);
209 v[3] = -364;
210 try expect(v[2] == 42);
211 try expect(-364 == v[3]);
212
213 storev(&v[0], 100);
214 try expect(v[0] == 100);
215 }
216 fn storev(ptr: anytype, x: i32) void {
217 ptr.* = x;
218 }
219 };
220
221 try S.doTheTest();
222 comptime try S.doTheTest();
223}
224
225test "load vector elements via runtime index" {
226 const S = struct {
227 fn doTheTest() !void {
228 var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
229 var i: u32 = 0;
230 try expect(v[i] == 1);
231 i += 1;
232 try expect(v[i] == 2);
233 i += 1;
234 try expect(v[i] == 3);
235 }
236 };
237
238 try S.doTheTest();
239 comptime try S.doTheTest();
240}
241
242test "store vector elements via runtime index" {
243 const S = struct {
244 fn doTheTest() !void {
245 var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
246 var i: u32 = 2;
247 v[i] = 1;
248 try expect(v[1] == 5);
249 try expect(v[2] == 1);
250 i += 1;
251 v[i] = -364;
252 try expect(-364 == v[3]);
253 }
254 };
255
256 try S.doTheTest();
257 comptime try S.doTheTest();
258}
259
260test "initialize vector which is a struct field" {
261 const Vec4Obj = struct {
262 data: Vector(4, f32),
263 };
264
265 const S = struct {
266 fn doTheTest() !void {
267 var foo = Vec4Obj{
268 .data = [_]f32{ 1, 2, 3, 4 },
269 };
270 }
271 };
272 try S.doTheTest();
273 comptime try S.doTheTest();
274}
275
276test "vector comparison operators" {
277 const S = struct {
278 fn doTheTest() !void {
279 {
280 const v1: Vector(4, bool) = [_]bool{ true, false, true, false };
281 const v2: Vector(4, bool) = [_]bool{ false, true, false, true };
282 try expectEqual(@splat(4, true), v1 == v1);
283 try expectEqual(@splat(4, false), v1 == v2);
284 try expectEqual(@splat(4, true), v1 != v2);
285 try expectEqual(@splat(4, false), v2 != v2);
286 }
287 {
288 const v1 = @splat(4, @as(u32, 0xc0ffeeee));
289 const v2: Vector(4, c_uint) = v1;
290 const v3 = @splat(4, @as(u32, 0xdeadbeef));
291 try expectEqual(@splat(4, true), v1 == v2);
292 try expectEqual(@splat(4, false), v1 == v3);
293 try expectEqual(@splat(4, true), v1 != v3);
294 try expectEqual(@splat(4, false), v1 != v2);
295 }
296 {
297 // Comptime-known LHS/RHS
298 var v1: @Vector(4, u32) = [_]u32{ 2, 1, 2, 1 };
299 const v2 = @splat(4, @as(u32, 2));
300 const v3: @Vector(4, bool) = [_]bool{ true, false, true, false };
301 try expectEqual(v3, v1 == v2);
302 try expectEqual(v3, v2 == v1);
303 }
304 }
305 };
306 try S.doTheTest();
307 comptime try S.doTheTest();
308}
309
310test "vector division operators" {
311 const S = struct {
312 fn doTheTestDiv(comptime T: type, x: Vector(4, T), y: Vector(4, T)) !void {
313 if (!comptime std.meta.trait.isSignedInt(T)) {
314 const d0 = x / y;
315 for (@as([4]T, d0)) |v, i| {
316 try expectEqual(x[i] / y[i], v);
317 }
318 }
319 const d1 = @divExact(x, y);
320 for (@as([4]T, d1)) |v, i| {
321 try expectEqual(@divExact(x[i], y[i]), v);
322 }
323 const d2 = @divFloor(x, y);
324 for (@as([4]T, d2)) |v, i| {
325 try expectEqual(@divFloor(x[i], y[i]), v);
326 }
327 const d3 = @divTrunc(x, y);
328 for (@as([4]T, d3)) |v, i| {
329 try expectEqual(@divTrunc(x[i], y[i]), v);
330 }
331 }
332
333 fn doTheTestMod(comptime T: type, x: Vector(4, T), y: Vector(4, T)) !void {
334 if ((!comptime std.meta.trait.isSignedInt(T)) and @typeInfo(T) != .Float) {
335 const r0 = x % y;
336 for (@as([4]T, r0)) |v, i| {
337 try expectEqual(x[i] % y[i], v);
338 }
339 }
340 const r1 = @mod(x, y);
341 for (@as([4]T, r1)) |v, i| {
342 try expectEqual(@mod(x[i], y[i]), v);
343 }
344 const r2 = @rem(x, y);
345 for (@as([4]T, r2)) |v, i| {
346 try expectEqual(@rem(x[i], y[i]), v);
347 }
348 }
349
350 fn doTheTest() !void {
351 // https://github.com/ziglang/zig/issues/4952
352 if (builtin.target.os.tag != .windows) {
353 try doTheTestDiv(f16, [4]f16{ 4.0, -4.0, 4.0, -4.0 }, [4]f16{ 1.0, 2.0, -1.0, -2.0 });
354 }
355
356 try doTheTestDiv(f32, [4]f32{ 4.0, -4.0, 4.0, -4.0 }, [4]f32{ 1.0, 2.0, -1.0, -2.0 });
357 try doTheTestDiv(f64, [4]f64{ 4.0, -4.0, 4.0, -4.0 }, [4]f64{ 1.0, 2.0, -1.0, -2.0 });
358
359 // https://github.com/ziglang/zig/issues/4952
360 if (builtin.target.os.tag != .windows) {
361 try doTheTestMod(f16, [4]f16{ 4.0, -4.0, 4.0, -4.0 }, [4]f16{ 1.0, 2.0, 0.5, 3.0 });
362 }
363 try doTheTestMod(f32, [4]f32{ 4.0, -4.0, 4.0, -4.0 }, [4]f32{ 1.0, 2.0, 0.5, 3.0 });
364 try doTheTestMod(f64, [4]f64{ 4.0, -4.0, 4.0, -4.0 }, [4]f64{ 1.0, 2.0, 0.5, 3.0 });
365
366 try doTheTestDiv(i8, [4]i8{ 4, -4, 4, -4 }, [4]i8{ 1, 2, -1, -2 });
367 try doTheTestDiv(i16, [4]i16{ 4, -4, 4, -4 }, [4]i16{ 1, 2, -1, -2 });
368 try doTheTestDiv(i32, [4]i32{ 4, -4, 4, -4 }, [4]i32{ 1, 2, -1, -2 });
369 try doTheTestDiv(i64, [4]i64{ 4, -4, 4, -4 }, [4]i64{ 1, 2, -1, -2 });
370
371 try doTheTestMod(i8, [4]i8{ 4, -4, 4, -4 }, [4]i8{ 1, 2, 4, 8 });
372 try doTheTestMod(i16, [4]i16{ 4, -4, 4, -4 }, [4]i16{ 1, 2, 4, 8 });
373 try doTheTestMod(i32, [4]i32{ 4, -4, 4, -4 }, [4]i32{ 1, 2, 4, 8 });
374 try doTheTestMod(i64, [4]i64{ 4, -4, 4, -4 }, [4]i64{ 1, 2, 4, 8 });
375
376 try doTheTestDiv(u8, [4]u8{ 1, 2, 4, 8 }, [4]u8{ 1, 1, 2, 4 });
377 try doTheTestDiv(u16, [4]u16{ 1, 2, 4, 8 }, [4]u16{ 1, 1, 2, 4 });
378 try doTheTestDiv(u32, [4]u32{ 1, 2, 4, 8 }, [4]u32{ 1, 1, 2, 4 });
379 try doTheTestDiv(u64, [4]u64{ 1, 2, 4, 8 }, [4]u64{ 1, 1, 2, 4 });
380
381 try doTheTestMod(u8, [4]u8{ 1, 2, 4, 8 }, [4]u8{ 1, 1, 2, 4 });
382 try doTheTestMod(u16, [4]u16{ 1, 2, 4, 8 }, [4]u16{ 1, 1, 2, 4 });
383 try doTheTestMod(u32, [4]u32{ 1, 2, 4, 8 }, [4]u32{ 1, 1, 2, 4 });
384 try doTheTestMod(u64, [4]u64{ 1, 2, 4, 8 }, [4]u64{ 1, 1, 2, 4 });
385 }
386 };
387
388 try S.doTheTest();
389 comptime try S.doTheTest();
390}
391
392test "vector bitwise not operator" {
393 const S = struct {
394 fn doTheTestNot(comptime T: type, x: Vector(4, T)) !void {
395 var y = ~x;
396 for (@as([4]T, y)) |v, i| {
397 try expectEqual(~x[i], v);
398 }
399 }
400 fn doTheTest() !void {
401 try doTheTestNot(u8, [_]u8{ 0, 2, 4, 255 });
402 try doTheTestNot(u16, [_]u16{ 0, 2, 4, 255 });
403 try doTheTestNot(u32, [_]u32{ 0, 2, 4, 255 });
404 try doTheTestNot(u64, [_]u64{ 0, 2, 4, 255 });
405
406 try doTheTestNot(u8, [_]u8{ 0, 2, 4, 255 });
407 try doTheTestNot(u16, [_]u16{ 0, 2, 4, 255 });
408 try doTheTestNot(u32, [_]u32{ 0, 2, 4, 255 });
409 try doTheTestNot(u64, [_]u64{ 0, 2, 4, 255 });
410 }
411 };
412
413 try S.doTheTest();
414 comptime try S.doTheTest();
415}
416
417test "vector shift operators" {
418 // TODO investigate why this fails when cross-compiled to wasm.
419 if (builtin.target.os.tag == .wasi) return error.SkipZigTest;
420
421 const S = struct {
422 fn doTheTestShift(x: anytype, y: anytype) !void {
423 const N = @typeInfo(@TypeOf(x)).Array.len;
424 const TX = @typeInfo(@TypeOf(x)).Array.child;
425 const TY = @typeInfo(@TypeOf(y)).Array.child;
426
427 var xv = @as(Vector(N, TX), x);
428 var yv = @as(Vector(N, TY), y);
429
430 var z0 = xv >> yv;
431 for (@as([N]TX, z0)) |v, i| {
432 try expectEqual(x[i] >> y[i], v);
433 }
434 var z1 = xv << yv;
435 for (@as([N]TX, z1)) |v, i| {
436 try expectEqual(x[i] << y[i], v);
437 }
438 }
439 fn doTheTestShiftExact(x: anytype, y: anytype, dir: enum { Left, Right }) !void {
440 const N = @typeInfo(@TypeOf(x)).Array.len;
441 const TX = @typeInfo(@TypeOf(x)).Array.child;
442 const TY = @typeInfo(@TypeOf(y)).Array.child;
443
444 var xv = @as(Vector(N, TX), x);
445 var yv = @as(Vector(N, TY), y);
446
447 var z = if (dir == .Left) @shlExact(xv, yv) else @shrExact(xv, yv);
448 for (@as([N]TX, z)) |v, i| {
449 const check = if (dir == .Left) x[i] << y[i] else x[i] >> y[i];
450 try expectEqual(check, v);
451 }
452 }
453 fn doTheTest() !void {
454 try doTheTestShift([_]u8{ 0, 2, 4, math.maxInt(u8) }, [_]u3{ 2, 0, 2, 7 });
455 try doTheTestShift([_]u16{ 0, 2, 4, math.maxInt(u16) }, [_]u4{ 2, 0, 2, 15 });
456 try doTheTestShift([_]u24{ 0, 2, 4, math.maxInt(u24) }, [_]u5{ 2, 0, 2, 23 });
457 try doTheTestShift([_]u32{ 0, 2, 4, math.maxInt(u32) }, [_]u5{ 2, 0, 2, 31 });
458 try doTheTestShift([_]u64{ 0xfe, math.maxInt(u64) }, [_]u6{ 0, 63 });
459
460 try doTheTestShift([_]i8{ 0, 2, 4, math.maxInt(i8) }, [_]u3{ 2, 0, 2, 7 });
461 try doTheTestShift([_]i16{ 0, 2, 4, math.maxInt(i16) }, [_]u4{ 2, 0, 2, 7 });
462 try doTheTestShift([_]i24{ 0, 2, 4, math.maxInt(i24) }, [_]u5{ 2, 0, 2, 7 });
463 try doTheTestShift([_]i32{ 0, 2, 4, math.maxInt(i32) }, [_]u5{ 2, 0, 2, 7 });
464 try doTheTestShift([_]i64{ 0xfe, math.maxInt(i64) }, [_]u6{ 0, 63 });
465
466 try doTheTestShiftExact([_]u8{ 0, 1, 1 << 7, math.maxInt(u8) ^ 1 }, [_]u3{ 4, 0, 7, 1 }, .Right);
467 try doTheTestShiftExact([_]u16{ 0, 1, 1 << 15, math.maxInt(u16) ^ 1 }, [_]u4{ 4, 0, 15, 1 }, .Right);
468 try doTheTestShiftExact([_]u24{ 0, 1, 1 << 23, math.maxInt(u24) ^ 1 }, [_]u5{ 4, 0, 23, 1 }, .Right);
469 try doTheTestShiftExact([_]u32{ 0, 1, 1 << 31, math.maxInt(u32) ^ 1 }, [_]u5{ 4, 0, 31, 1 }, .Right);
470 try doTheTestShiftExact([_]u64{ 1 << 63, 1 }, [_]u6{ 63, 0 }, .Right);
471
472 try doTheTestShiftExact([_]u8{ 0, 1, 1, math.maxInt(u8) ^ (1 << 7) }, [_]u3{ 4, 0, 7, 1 }, .Left);
473 try doTheTestShiftExact([_]u16{ 0, 1, 1, math.maxInt(u16) ^ (1 << 15) }, [_]u4{ 4, 0, 15, 1 }, .Left);
474 try doTheTestShiftExact([_]u24{ 0, 1, 1, math.maxInt(u24) ^ (1 << 23) }, [_]u5{ 4, 0, 23, 1 }, .Left);
475 try doTheTestShiftExact([_]u32{ 0, 1, 1, math.maxInt(u32) ^ (1 << 31) }, [_]u5{ 4, 0, 31, 1 }, .Left);
476 try doTheTestShiftExact([_]u64{ 1 << 63, 1 }, [_]u6{ 0, 63 }, .Left);
477 }
478 };
479
480 switch (builtin.target.cpu.arch) {
481 .i386,
482 .aarch64,
483 .aarch64_be,
484 .aarch64_32,
485 .arm,
486 .armeb,
487 .thumb,
488 .thumbeb,
489 .mips,
490 .mipsel,
491 .mips64,
492 .mips64el,
493 .riscv64,
494 .sparcv9,
495 => {
496 // LLVM miscompiles on this architecture
497 // https://github.com/ziglang/zig/issues/4951
498 return error.SkipZigTest;
499 },
500 else => {},
501 }
502
503 try S.doTheTest();
504 comptime try S.doTheTest();
505}
506
507test "vector reduce operation" {
508 const S = struct {
509 fn doTheTestReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {
510 const N = @typeInfo(@TypeOf(x)).Array.len;
511 const TX = @typeInfo(@TypeOf(x)).Array.child;
512
513 var r = @reduce(op, @as(Vector(N, TX), x));
514 switch (@typeInfo(TX)) {
515 .Int, .Bool => try expectEqual(expected, r),
516 .Float => {
517 const expected_nan = math.isNan(expected);
518 const got_nan = math.isNan(r);
519
520 if (expected_nan and got_nan) {
521 // Do this check explicitly as two NaN values are never
522 // equal.
523 } else {
524 try expectApproxEqRel(expected, r, math.sqrt(math.epsilon(TX)));
525 }
526 },
527 else => unreachable,
528 }
529 }
530 fn doTheTest() !void {
531 try doTheTestReduce(.Add, [4]i16{ -9, -99, -999, -9999 }, @as(i32, -11106));
532 try doTheTestReduce(.Add, [4]u16{ 9, 99, 999, 9999 }, @as(u32, 11106));
533 try doTheTestReduce(.Add, [4]i32{ -9, -99, -999, -9999 }, @as(i32, -11106));
534 try doTheTestReduce(.Add, [4]u32{ 9, 99, 999, 9999 }, @as(u32, 11106));
535 try doTheTestReduce(.Add, [4]i64{ -9, -99, -999, -9999 }, @as(i64, -11106));
536 try doTheTestReduce(.Add, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 11106));
537 try doTheTestReduce(.Add, [4]i128{ -9, -99, -999, -9999 }, @as(i128, -11106));
538 try doTheTestReduce(.Add, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 11106));
539 try doTheTestReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9));
540 try doTheTestReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9));
541 try doTheTestReduce(.Add, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 42.9));
542
543 try doTheTestReduce(.And, [4]bool{ true, false, true, true }, @as(bool, false));
544 try doTheTestReduce(.And, [4]u1{ 1, 0, 1, 1 }, @as(u1, 0));
545 try doTheTestReduce(.And, [4]u16{ 0xffff, 0xff55, 0xaaff, 0x1010 }, @as(u16, 0x10));
546 try doTheTestReduce(.And, [4]u32{ 0xffffffff, 0xffff5555, 0xaaaaffff, 0x10101010 }, @as(u32, 0x1010));
547 try doTheTestReduce(.And, [4]u64{ 0xffffffff, 0xffff5555, 0xaaaaffff, 0x10101010 }, @as(u64, 0x1010));
548
549 try doTheTestReduce(.Min, [4]i16{ -1, 2, 3, 4 }, @as(i16, -1));
550 try doTheTestReduce(.Min, [4]u16{ 1, 2, 3, 4 }, @as(u16, 1));
551 try doTheTestReduce(.Min, [4]i32{ 1234567, -386, 0, 3 }, @as(i32, -386));
552 try doTheTestReduce(.Min, [4]u32{ 99, 9999, 9, 99999 }, @as(u32, 9));
553
554 // LLVM 11 ERROR: Cannot select type
555 // https://github.com/ziglang/zig/issues/7138
556 if (builtin.target.cpu.arch != .aarch64) {
557 try doTheTestReduce(.Min, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, -386));
558 try doTheTestReduce(.Min, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 9));
559 }
560
561 try doTheTestReduce(.Min, [4]i128{ 1234567, -386, 0, 3 }, @as(i128, -386));
562 try doTheTestReduce(.Min, [4]u128{ 99, 9999, 9, 99999 }, @as(u128, 9));
563 try doTheTestReduce(.Min, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, -100.0));
564 try doTheTestReduce(.Min, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, -100.0));
565 try doTheTestReduce(.Min, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, -100.0));
566
567 try doTheTestReduce(.Max, [4]i16{ -1, 2, 3, 4 }, @as(i16, 4));
568 try doTheTestReduce(.Max, [4]u16{ 1, 2, 3, 4 }, @as(u16, 4));
569 try doTheTestReduce(.Max, [4]i32{ 1234567, -386, 0, 3 }, @as(i32, 1234567));
570 try doTheTestReduce(.Max, [4]u32{ 99, 9999, 9, 99999 }, @as(u32, 99999));
571
572 // LLVM 11 ERROR: Cannot select type
573 // https://github.com/ziglang/zig/issues/7138
574 if (builtin.target.cpu.arch != .aarch64) {
575 try doTheTestReduce(.Max, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, 1234567));
576 try doTheTestReduce(.Max, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 99999));
577 }
578
579 try doTheTestReduce(.Max, [4]i128{ 1234567, -386, 0, 3 }, @as(i128, 1234567));
580 try doTheTestReduce(.Max, [4]u128{ 99, 9999, 9, 99999 }, @as(u128, 99999));
581 try doTheTestReduce(.Max, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, 10.0e9));
582 try doTheTestReduce(.Max, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, 10.0e9));
583 try doTheTestReduce(.Max, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, 10.0e9));
584
585 try doTheTestReduce(.Mul, [4]i16{ -1, 2, 3, 4 }, @as(i16, -24));
586 try doTheTestReduce(.Mul, [4]u16{ 1, 2, 3, 4 }, @as(u16, 24));
587 try doTheTestReduce(.Mul, [4]i32{ -9, -99, -999, 999 }, @as(i32, -889218891));
588 try doTheTestReduce(.Mul, [4]u32{ 1, 2, 3, 4 }, @as(u32, 24));
589 try doTheTestReduce(.Mul, [4]i64{ 9, 99, 999, 9999 }, @as(i64, 8900199891));
590 try doTheTestReduce(.Mul, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 8900199891));
591 try doTheTestReduce(.Mul, [4]i128{ -9, -99, -999, 9999 }, @as(i128, -8900199891));
592 try doTheTestReduce(.Mul, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 8900199891));
593 try doTheTestReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7));
594 try doTheTestReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7));
595 try doTheTestReduce(.Mul, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 58430.7));
596
597 try doTheTestReduce(.Or, [4]bool{ false, true, false, false }, @as(bool, true));
598 try doTheTestReduce(.Or, [4]u1{ 0, 1, 0, 0 }, @as(u1, 1));
599 try doTheTestReduce(.Or, [4]u16{ 0xff00, 0xff00, 0xf0, 0xf }, ~@as(u16, 0));
600 try doTheTestReduce(.Or, [4]u32{ 0xffff0000, 0xff00, 0xf0, 0xf }, ~@as(u32, 0));
601 try doTheTestReduce(.Or, [4]u64{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u64, 0xffffffff));
602 try doTheTestReduce(.Or, [4]u128{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u128, 0xffffffff));
603
604 try doTheTestReduce(.Xor, [4]bool{ true, true, true, false }, @as(bool, true));
605 try doTheTestReduce(.Xor, [4]u1{ 1, 1, 1, 0 }, @as(u1, 1));
606 try doTheTestReduce(.Xor, [4]u16{ 0x0000, 0x3333, 0x8888, 0x4444 }, ~@as(u16, 0));
607 try doTheTestReduce(.Xor, [4]u32{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, ~@as(u32, 0));
608 try doTheTestReduce(.Xor, [4]u64{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, @as(u64, 0xffffffff));
609 try doTheTestReduce(.Xor, [4]u128{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, @as(u128, 0xffffffff));
610
611 // Test the reduction on vectors containing NaNs.
612 const f16_nan = math.nan(f16);
613 const f32_nan = math.nan(f32);
614 const f64_nan = math.nan(f64);
615
616 try doTheTestReduce(.Add, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
617 try doTheTestReduce(.Add, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
618 try doTheTestReduce(.Add, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
619
620 // LLVM 11 ERROR: Cannot select type
621 // https://github.com/ziglang/zig/issues/7138
622 if (false) {
623 try doTheTestReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
624 try doTheTestReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
625 try doTheTestReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
626
627 try doTheTestReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
628 try doTheTestReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
629 try doTheTestReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
630 }
631
632 try doTheTestReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
633 try doTheTestReduce(.Mul, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
634 try doTheTestReduce(.Mul, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
635 }
636 };
637
638 try S.doTheTest();
639 comptime try S.doTheTest();
640}
test/behavior/void.zig created+40
...@@ -0,0 +1,40 @@
1const expect = @import("std").testing.expect;
2
3const Foo = struct {
4 a: void,
5 b: i32,
6 c: void,
7};
8
9test "compare void with void compile time known" {
10 comptime {
11 const foo = Foo{
12 .a = {},
13 .b = 1,
14 .c = {},
15 };
16 try expect(foo.a == {});
17 }
18}
19
20test "iterate over a void slice" {
21 var j: usize = 0;
22 for (times(10)) |_, i| {
23 try expect(i == j);
24 j += 1;
25 }
26}
27
28fn times(n: usize) []const void {
29 return @as([*]void, undefined)[0..n];
30}
31
32test "void optional" {
33 var x: ?void = {};
34 try expect(x != null);
35}
36
37test "void array as a local variable initializer" {
38 var x = [_]void{{}} ** 1004;
39 var y = x[0];
40}
test/behavior/wasm.zig created+8
...@@ -0,0 +1,8 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "memory size and grow" {
5 var prev = @wasmMemorySize(0);
6 try expect(prev == @wasmMemoryGrow(0, 1));
7 try expect(prev + 1 == @wasmMemorySize(0));
8}
test/behavior/while.zig created+283
...@@ -0,0 +1,283 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "while loop" {
5 var i: i32 = 0;
6 while (i < 4) {
7 i += 1;
8 }
9 try expect(i == 4);
10 try expect(whileLoop1() == 1);
11}
12fn whileLoop1() i32 {
13 return whileLoop2();
14}
15fn whileLoop2() i32 {
16 while (true) {
17 return 1;
18 }
19}
20
21test "static eval while" {
22 try expect(static_eval_while_number == 1);
23}
24const static_eval_while_number = staticWhileLoop1();
25fn staticWhileLoop1() i32 {
26 return whileLoop2();
27}
28fn staticWhileLoop2() i32 {
29 while (true) {
30 return 1;
31 }
32}
33
34test "continue and break" {
35 try runContinueAndBreakTest();
36 try expect(continue_and_break_counter == 8);
37}
38var continue_and_break_counter: i32 = 0;
39fn runContinueAndBreakTest() !void {
40 var i: i32 = 0;
41 while (true) {
42 continue_and_break_counter += 2;
43 i += 1;
44 if (i < 4) {
45 continue;
46 }
47 break;
48 }
49 try expect(i == 4);
50}
51
52test "return with implicit cast from while loop" {
53 returnWithImplicitCastFromWhileLoopTest() catch unreachable;
54}
55fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
56 while (true) {
57 return;
58 }
59}
60
61test "while with continue expression" {
62 var sum: i32 = 0;
63 {
64 var i: i32 = 0;
65 while (i < 10) : (i += 1) {
66 if (i == 5) continue;
67 sum += i;
68 }
69 }
70 try expect(sum == 40);
71}
72
73test "while with else" {
74 var sum: i32 = 0;
75 var i: i32 = 0;
76 var got_else: i32 = 0;
77 while (i < 10) : (i += 1) {
78 sum += 1;
79 } else {
80 got_else += 1;
81 }
82 try expect(sum == 10);
83 try expect(got_else == 1);
84}
85
86test "while with optional as condition" {
87 numbers_left = 10;
88 var sum: i32 = 0;
89 while (getNumberOrNull()) |value| {
90 sum += value;
91 }
92 try expect(sum == 45);
93}
94
95test "while with optional as condition with else" {
96 numbers_left = 10;
97 var sum: i32 = 0;
98 var got_else: i32 = 0;
99 while (getNumberOrNull()) |value| {
100 sum += value;
101 try expect(got_else == 0);
102 } else {
103 got_else += 1;
104 }
105 try expect(sum == 45);
106 try expect(got_else == 1);
107}
108
109test "while with error union condition" {
110 numbers_left = 10;
111 var sum: i32 = 0;
112 var got_else: i32 = 0;
113 while (getNumberOrErr()) |value| {
114 sum += value;
115 } else |err| {
116 try expect(err == error.OutOfNumbers);
117 got_else += 1;
118 }
119 try expect(sum == 45);
120 try expect(got_else == 1);
121}
122
123var numbers_left: i32 = undefined;
124fn getNumberOrErr() anyerror!i32 {
125 return if (numbers_left == 0) error.OutOfNumbers else x: {
126 numbers_left -= 1;
127 break :x numbers_left;
128 };
129}
130fn getNumberOrNull() ?i32 {
131 return if (numbers_left == 0) null else x: {
132 numbers_left -= 1;
133 break :x numbers_left;
134 };
135}
136
137test "while on optional with else result follow else prong" {
138 const result = while (returnNull()) |value| {
139 break value;
140 } else @as(i32, 2);
141 try expect(result == 2);
142}
143
144test "while on optional with else result follow break prong" {
145 const result = while (returnOptional(10)) |value| {
146 break value;
147 } else @as(i32, 2);
148 try expect(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| @as(i32, 2);
155 try expect(result == 2);
156}
157
158test "while on error union with else result follow break prong" {
159 const result = while (returnSuccess(10)) |value| {
160 break value;
161 } else |err| @as(i32, 2);
162 try expect(result == 10);
163}
164
165test "while on bool with else result follow else prong" {
166 const result = while (returnFalse()) {
167 break @as(i32, 10);
168 } else @as(i32, 2);
169 try expect(result == 2);
170}
171
172test "while on bool with else result follow break prong" {
173 const result = while (returnTrue()) {
174 break @as(i32, 10);
175 } else @as(i32, 2);
176 try expect(result == 10);
177}
178
179test "break from outer while loop" {
180 testBreakOuter();
181 comptime testBreakOuter();
182}
183
184fn testBreakOuter() void {
185 outer: while (true) {
186 while (true) {
187 break :outer;
188 }
189 }
190}
191
192test "continue outer while loop" {
193 testContinueOuter();
194 comptime testContinueOuter();
195}
196
197fn testContinueOuter() void {
198 var i: usize = 0;
199 outer: while (i < 10) : (i += 1) {
200 while (true) {
201 continue :outer;
202 }
203 }
204}
205
206fn returnNull() ?i32 {
207 return null;
208}
209fn returnOptional(x: i32) ?i32 {
210 return x;
211}
212fn returnError() anyerror!i32 {
213 return error.YouWantedAnError;
214}
215fn returnSuccess(x: i32) anyerror!i32 {
216 return x;
217}
218fn returnFalse() bool {
219 return false;
220}
221fn returnTrue() bool {
222 return true;
223}
224
225test "while bool 2 break statements and an else" {
226 const S = struct {
227 fn entry(t: bool, f: bool) !void {
228 var ok = false;
229 ok = while (t) {
230 if (f) break false;
231 if (t) break true;
232 } else false;
233 try expect(ok);
234 }
235 };
236 try S.entry(true, false);
237 comptime try S.entry(true, false);
238}
239
240test "while optional 2 break statements and an else" {
241 const S = struct {
242 fn entry(opt_t: ?bool, f: bool) !void {
243 var ok = false;
244 ok = while (opt_t) |t| {
245 if (f) break false;
246 if (t) break true;
247 } else false;
248 try expect(ok);
249 }
250 };
251 try S.entry(true, false);
252 comptime try S.entry(true, false);
253}
254
255test "while error 2 break statements and an else" {
256 const S = struct {
257 fn entry(opt_t: anyerror!bool, f: bool) !void {
258 var ok = false;
259 ok = while (opt_t) |t| {
260 if (f) break false;
261 if (t) break true;
262 } else |_| false;
263 try expect(ok);
264 }
265 };
266 try S.entry(true, false);
267 comptime try S.entry(true, false);
268}
269
270test "while copies its payload" {
271 const S = struct {
272 fn doTheTest() !void {
273 var tmp: ?i32 = 10;
274 while (tmp) |value| {
275 // Modify the original variable
276 tmp = null;
277 try expect(value == 10);
278 }
279 }
280 };
281 try S.doTheTest();
282 comptime try S.doTheTest();
283}
test/behavior/widening.zig created+39
...@@ -0,0 +1,39 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4
5test "integer widening" {
6 var a: u8 = 250;
7 var b: u16 = a;
8 var c: u32 = b;
9 var d: u64 = c;
10 var e: u64 = d;
11 var f: u128 = e;
12 try expect(f == a);
13}
14
15test "implicit unsigned integer to signed integer" {
16 var a: u8 = 250;
17 var b: i16 = a;
18 try expect(b == 250);
19}
20
21test "float widening" {
22 var a: f16 = 12.34;
23 var b: f32 = a;
24 var c: f64 = b;
25 var d: f128 = c;
26 try expect(a == b);
27 try expect(b == c);
28 try expect(c == d);
29}
30
31test "float widening f16 to f128" {
32 // TODO https://github.com/ziglang/zig/issues/3282
33 if (@import("builtin").target.cpu.arch == .aarch64) return error.SkipZigTest;
34 if (@import("builtin").target.cpu.arch == .powerpc64le) return error.SkipZigTest;
35
36 var x: f16 = 12.34;
37 var y: f128 = x;
38 try expect(x == y);
39}
test/cli.zig+1-1
...@@ -115,7 +115,7 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {...@@ -115,7 +115,7 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {
115 \\ return num * num;115 \\ return num * num;
116 \\}116 \\}
117 \\extern fn zig_panic() noreturn;117 \\extern fn zig_panic() noreturn;
118 \\pub fn panic(msg: []const u8, error_return_trace: ?*@import("builtin").StackTrace) noreturn {118 \\pub fn panic(msg: []const u8, error_return_trace: ?*@import("std").builtin.StackTrace) noreturn {
119 \\ zig_panic();119 \\ zig_panic();
120 \\}120 \\}
121 );121 );
test/compile_errors.zig+24-24
...@@ -208,7 +208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -208,7 +208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
208 });208 });
209209
210 cases.add("@Type with TypeInfo.Int",210 cases.add("@Type with TypeInfo.Int",
211 \\const builtin = @import("builtin");211 \\const builtin = @import("std").builtin;
212 \\export fn entry() void {212 \\export fn entry() void {
213 \\ _ = @Type(builtin.TypeInfo.Int {213 \\ _ = @Type(builtin.TypeInfo.Int {
214 \\ .signedness = .signed,214 \\ .signedness = .signed,
...@@ -242,7 +242,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -242,7 +242,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
242 });242 });
243243
244 cases.add("@Type for exhaustive enum with undefined tag type",244 cases.add("@Type for exhaustive enum with undefined tag type",
245 \\const TypeInfo = @import("builtin").TypeInfo;245 \\const TypeInfo = @import("std").builtin.TypeInfo;
246 \\const Tag = @Type(.{246 \\const Tag = @Type(.{
247 \\ .Enum = .{247 \\ .Enum = .{
248 \\ .layout = .Auto,248 \\ .layout = .Auto,
...@@ -272,7 +272,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -272,7 +272,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
272 });272 });
273273
274 cases.add("@Type for exhaustive enum with non-integer tag type",274 cases.add("@Type for exhaustive enum with non-integer tag type",
275 \\const TypeInfo = @import("builtin").TypeInfo;275 \\const TypeInfo = @import("std").builtin.TypeInfo;
276 \\const Tag = @Type(.{276 \\const Tag = @Type(.{
277 \\ .Enum = .{277 \\ .Enum = .{
278 \\ .layout = .Auto,278 \\ .layout = .Auto,
...@@ -331,7 +331,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -331,7 +331,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
331 });331 });
332332
333 cases.add("@Type for tagged union with extra enum field",333 cases.add("@Type for tagged union with extra enum field",
334 \\const TypeInfo = @import("builtin").TypeInfo;334 \\const TypeInfo = @import("std").builtin.TypeInfo;
335 \\const Tag = @Type(.{335 \\const Tag = @Type(.{
336 \\ .Enum = .{336 \\ .Enum = .{
337 \\ .layout = .Auto,337 \\ .layout = .Auto,
...@@ -397,7 +397,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -397,7 +397,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
397 \\ .is_generic = true,397 \\ .is_generic = true,
398 \\ .is_var_args = false,398 \\ .is_var_args = false,
399 \\ .return_type = u0,399 \\ .return_type = u0,
400 \\ .args = &[_]@import("builtin").TypeInfo.FnArg{},400 \\ .args = &[_]@import("std").builtin.TypeInfo.FnArg{},
401 \\ },401 \\ },
402 \\});402 \\});
403 \\comptime { _ = Foo; }403 \\comptime { _ = Foo; }
...@@ -413,7 +413,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -413,7 +413,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
413 \\ .is_generic = false,413 \\ .is_generic = false,
414 \\ .is_var_args = true,414 \\ .is_var_args = true,
415 \\ .return_type = u0,415 \\ .return_type = u0,
416 \\ .args = &[_]@import("builtin").TypeInfo.FnArg{},416 \\ .args = &[_]@import("std").builtin.TypeInfo.FnArg{},
417 \\ },417 \\ },
418 \\});418 \\});
419 \\comptime { _ = Foo; }419 \\comptime { _ = Foo; }
...@@ -429,7 +429,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -429,7 +429,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
429 \\ .is_generic = false,429 \\ .is_generic = false,
430 \\ .is_var_args = false,430 \\ .is_var_args = false,
431 \\ .return_type = null,431 \\ .return_type = null,
432 \\ .args = &[_]@import("builtin").TypeInfo.FnArg{},432 \\ .args = &[_]@import("std").builtin.TypeInfo.FnArg{},
433 \\ },433 \\ },
434 \\});434 \\});
435 \\comptime { _ = Foo; }435 \\comptime { _ = Foo; }
...@@ -438,7 +438,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -438,7 +438,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
438 });438 });
439439
440 cases.add("@Type for union with opaque field",440 cases.add("@Type for union with opaque field",
441 \\const TypeInfo = @import("builtin").TypeInfo;441 \\const TypeInfo = @import("std").builtin.TypeInfo;
442 \\const Untagged = @Type(.{442 \\const Untagged = @Type(.{
443 \\ .Union = .{443 \\ .Union = .{
444 \\ .layout = .Auto,444 \\ .layout = .Auto,
...@@ -474,7 +474,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -474,7 +474,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
474 });474 });
475475
476 cases.add("@Type for union with zero fields",476 cases.add("@Type for union with zero fields",
477 \\const TypeInfo = @import("builtin").TypeInfo;477 \\const TypeInfo = @import("std").builtin.TypeInfo;
478 \\const Untagged = @Type(.{478 \\const Untagged = @Type(.{
479 \\ .Union = .{479 \\ .Union = .{
480 \\ .layout = .Auto,480 \\ .layout = .Auto,
...@@ -492,7 +492,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -492,7 +492,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
492 });492 });
493493
494 cases.add("@Type for exhaustive enum with zero fields",494 cases.add("@Type for exhaustive enum with zero fields",
495 \\const TypeInfo = @import("builtin").TypeInfo;495 \\const TypeInfo = @import("std").builtin.TypeInfo;
496 \\const Tag = @Type(.{496 \\const Tag = @Type(.{
497 \\ .Enum = .{497 \\ .Enum = .{
498 \\ .layout = .Auto,498 \\ .layout = .Auto,
...@@ -511,7 +511,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -511,7 +511,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
511 });511 });
512512
513 cases.add("@Type for tagged union with extra union field",513 cases.add("@Type for tagged union with extra union field",
514 \\const TypeInfo = @import("builtin").TypeInfo;514 \\const TypeInfo = @import("std").builtin.TypeInfo;
515 \\const Tag = @Type(.{515 \\const Tag = @Type(.{
516 \\ .Enum = .{516 \\ .Enum = .{
517 \\ .layout = .Auto,517 \\ .layout = .Auto,
...@@ -1946,7 +1946,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1946,7 +1946,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1946 });1946 });
19471947
1948 cases.add("attempt to create 17 bit float type",1948 cases.add("attempt to create 17 bit float type",
1949 \\const builtin = @import("builtin");1949 \\const builtin = @import("std").builtin;
1950 \\comptime {1950 \\comptime {
1951 \\ _ = @Type(builtin.TypeInfo { .Float = builtin.TypeInfo.Float { .bits = 17 } });1951 \\ _ = @Type(builtin.TypeInfo { .Float = builtin.TypeInfo.Float { .bits = 17 } });
1952 \\}1952 \\}
...@@ -1963,7 +1963,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1963,7 +1963,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1963 });1963 });
19641964
1965 cases.add("@Type with non-constant expression",1965 cases.add("@Type with non-constant expression",
1966 \\const builtin = @import("builtin");1966 \\const builtin = @import("std").builtin;
1967 \\var globalTypeInfo : builtin.TypeInfo = undefined;1967 \\var globalTypeInfo : builtin.TypeInfo = undefined;
1968 \\export fn entry() void {1968 \\export fn entry() void {
1969 \\ _ = @Type(globalTypeInfo);1969 \\ _ = @Type(globalTypeInfo);
...@@ -5963,7 +5963,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5963,7 +5963,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5963 });5963 });
59645964
5965 cases.add("atomic orderings of cmpxchg - failure stricter than success",5965 cases.add("atomic orderings of cmpxchg - failure stricter than success",
5966 \\const AtomicOrder = @import("builtin").AtomicOrder;5966 \\const AtomicOrder = @import("std").builtin.AtomicOrder;
5967 \\export fn f() void {5967 \\export fn f() void {
5968 \\ var x: i32 = 1234;5968 \\ var x: i32 = 1234;
5969 \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.Monotonic, AtomicOrder.SeqCst)) {}5969 \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.Monotonic, AtomicOrder.SeqCst)) {}
...@@ -5973,7 +5973,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5973,7 +5973,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5973 });5973 });
59745974
5975 cases.add("atomic orderings of cmpxchg - success Monotonic or stricter",5975 cases.add("atomic orderings of cmpxchg - success Monotonic or stricter",
5976 \\const AtomicOrder = @import("builtin").AtomicOrder;5976 \\const AtomicOrder = @import("std").builtin.AtomicOrder;
5977 \\export fn f() void {5977 \\export fn f() void {
5978 \\ var x: i32 = 1234;5978 \\ var x: i32 = 1234;
5979 \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.Unordered, AtomicOrder.Unordered)) {}5979 \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.Unordered, AtomicOrder.Unordered)) {}
...@@ -6579,12 +6579,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -6579,12 +6579,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6579 });6579 });
65806580
6581 cases.add("invalid member of builtin enum",6581 cases.add("invalid member of builtin enum",
6582 \\const builtin = @import("builtin",);6582 \\const builtin = @import("std").builtin;
6583 \\export fn entry() void {6583 \\export fn entry() void {
6584 \\ const foo = builtin.Arch.x86;6584 \\ const foo = builtin.Mode.x86;
6585 \\}6585 \\}
6586 , &[_][]const u8{6586 , &[_][]const u8{
6587 "tmp.zig:3:29: error: container 'std.target.Arch' has no member called 'x86'",6587 "tmp.zig:3:29: error: container 'std.builtin.Mode' has no member called 'x86'",
6588 });6588 });
65896589
6590 cases.add("int to ptr of 0 bits",6590 cases.add("int to ptr of 0 bits",
...@@ -6853,8 +6853,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -6853,8 +6853,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
68536853
6854 cases.add("@setFloatMode twice for same scope",6854 cases.add("@setFloatMode twice for same scope",
6855 \\export fn foo() void {6855 \\export fn foo() void {
6856 \\ @setFloatMode(@import("builtin").FloatMode.Optimized);6856 \\ @setFloatMode(@import("std").builtin.FloatMode.Optimized);
6857 \\ @setFloatMode(@import("builtin").FloatMode.Optimized);6857 \\ @setFloatMode(@import("std").builtin.FloatMode.Optimized);
6858 \\}6858 \\}
6859 , &[_][]const u8{6859 , &[_][]const u8{
6860 "tmp.zig:3:5: error: float mode set twice for same scope",6860 "tmp.zig:3:5: error: float mode set twice for same scope",
...@@ -7066,7 +7066,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -7066,7 +7066,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
7066 });7066 });
70677067
7068 cases.add("passing a not-aligned-enough pointer to cmpxchg",7068 cases.add("passing a not-aligned-enough pointer to cmpxchg",
7069 \\const AtomicOrder = @import("builtin").AtomicOrder;7069 \\const AtomicOrder = @import("std").builtin.AtomicOrder;
7070 \\export fn entry() bool {7070 \\export fn entry() bool {
7071 \\ var x: i32 align(1) = 1234;7071 \\ var x: i32 align(1) = 1234;
7072 \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}7072 \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}
...@@ -7233,7 +7233,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -7233,7 +7233,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
7233 });7233 });
72347234
7235 cases.add("storing runtime value in compile time variable then using it",7235 cases.add("storing runtime value in compile time variable then using it",
7236 \\const Mode = @import("builtin").Mode;7236 \\const Mode = @import("std").builtin.Mode;
7237 \\7237 \\
7238 \\fn Free(comptime filename: []const u8) TestCase {7238 \\fn Free(comptime filename: []const u8) TestCase {
7239 \\ return TestCase {7239 \\ return TestCase {
...@@ -7776,11 +7776,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -7776,11 +7776,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
7776 cases.addTest("nested vectors",7776 cases.addTest("nested vectors",
7777 \\export fn entry() void {7777 \\export fn entry() void {
7778 \\ const V1 = @import("std").meta.Vector(4, u8);7778 \\ const V1 = @import("std").meta.Vector(4, u8);
7779 \\ const V2 = @Type(@import("builtin").TypeInfo{ .Vector = .{ .len = 4, .child = V1 } });7779 \\ const V2 = @Type(@import("std").builtin.TypeInfo{ .Vector = .{ .len = 4, .child = V1 } });
7780 \\ var v: V2 = undefined;7780 \\ var v: V2 = undefined;
7781 \\}7781 \\}
7782 , &[_][]const u8{7782 , &[_][]const u8{
7783 "tmp.zig:3:49: error: vector element type must be integer, float, bool, or pointer; '@Vector(4, u8)' is invalid",7783 "tmp.zig:3:53: error: vector element type must be integer, float, bool, or pointer; '@Vector(4, u8)' is invalid",
7784 "tmp.zig:3:16: note: referenced here",7784 "tmp.zig:3:16: note: referenced here",
7785 });7785 });
77867786
test/runtime_safety.zig+186-138
...@@ -3,7 +3,7 @@ const tests = @import("tests.zig");...@@ -3,7 +3,7 @@ const tests = @import("tests.zig");
3pub fn addCases(cases: *tests.CompareOutputContext) void {3pub fn addCases(cases: *tests.CompareOutputContext) void {
4 {4 {
5 const check_panic_msg =5 const check_panic_msg =
6 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {6 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
7 \\ if (std.mem.eql(u8, message, "reached unreachable code")) {7 \\ if (std.mem.eql(u8, message, "reached unreachable code")) {
8 \\ std.process.exit(126); // good8 \\ std.process.exit(126); // good
9 \\ }9 \\ }
...@@ -44,7 +44,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -44,7 +44,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
4444
45 {45 {
46 const check_panic_msg =46 const check_panic_msg =
47 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {47 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
48 \\ if (std.mem.eql(u8, message, "invalid enum value")) {48 \\ if (std.mem.eql(u8, message, "invalid enum value")) {
49 \\ std.process.exit(126); // good49 \\ std.process.exit(126); // good
50 \\ }50 \\ }
...@@ -82,7 +82,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -82,7 +82,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
8282
83 {83 {
84 const check_panic_msg =84 const check_panic_msg =
85 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {85 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
86 \\ if (std.mem.eql(u8, message, "index out of bounds")) {86 \\ if (std.mem.eql(u8, message, "index out of bounds")) {
87 \\ std.process.exit(126); // good87 \\ std.process.exit(126); // good
88 \\ }88 \\ }
...@@ -152,7 +152,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -152,7 +152,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
152 cases.addRuntimeSafety("truncating vector cast",152 cases.addRuntimeSafety("truncating vector cast",
153 \\const std = @import("std");153 \\const std = @import("std");
154 \\const V = @import("std").meta.Vector;154 \\const V = @import("std").meta.Vector;
155 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {155 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
156 \\ if (std.mem.eql(u8, message, "integer cast truncated bits")) {156 \\ if (std.mem.eql(u8, message, "integer cast truncated bits")) {
157 \\ std.process.exit(126); // good157 \\ std.process.exit(126); // good
158 \\ }158 \\ }
...@@ -167,7 +167,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -167,7 +167,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
167 cases.addRuntimeSafety("unsigned-signed vector cast",167 cases.addRuntimeSafety("unsigned-signed vector cast",
168 \\const std = @import("std");168 \\const std = @import("std");
169 \\const V = @import("std").meta.Vector;169 \\const V = @import("std").meta.Vector;
170 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {170 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
171 \\ if (std.mem.eql(u8, message, "integer cast truncated bits")) {171 \\ if (std.mem.eql(u8, message, "integer cast truncated bits")) {
172 \\ std.process.exit(126); // good172 \\ std.process.exit(126); // good
173 \\ }173 \\ }
...@@ -182,7 +182,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -182,7 +182,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
182 cases.addRuntimeSafety("signed-unsigned vector cast",182 cases.addRuntimeSafety("signed-unsigned vector cast",
183 \\const std = @import("std");183 \\const std = @import("std");
184 \\const V = @import("std").meta.Vector;184 \\const V = @import("std").meta.Vector;
185 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {185 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
186 \\ if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) {186 \\ if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) {
187 \\ std.process.exit(126); // good187 \\ std.process.exit(126); // good
188 \\ }188 \\ }
...@@ -196,7 +196,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -196,7 +196,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
196196
197 cases.addRuntimeSafety("shift left by huge amount",197 cases.addRuntimeSafety("shift left by huge amount",
198 \\const std = @import("std");198 \\const std = @import("std");
199 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {199 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
200 \\ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {200 \\ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
201 \\ std.process.exit(126); // good201 \\ std.process.exit(126); // good
202 \\ }202 \\ }
...@@ -211,7 +211,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -211,7 +211,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
211211
212 cases.addRuntimeSafety("shift right by huge amount",212 cases.addRuntimeSafety("shift right by huge amount",
213 \\const std = @import("std");213 \\const std = @import("std");
214 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {214 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
215 \\ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {215 \\ if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
216 \\ std.process.exit(126); // good216 \\ std.process.exit(126); // good
217 \\ }217 \\ }
...@@ -226,7 +226,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -226,7 +226,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
226226
227 cases.addRuntimeSafety("slice sentinel mismatch - optional pointers",227 cases.addRuntimeSafety("slice sentinel mismatch - optional pointers",
228 \\const std = @import("std");228 \\const std = @import("std");
229 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {229 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
230 \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {230 \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {
231 \\ std.process.exit(126); // good231 \\ std.process.exit(126); // good
232 \\ }232 \\ }
...@@ -240,7 +240,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -240,7 +240,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
240240
241 cases.addRuntimeSafety("slice sentinel mismatch - floats",241 cases.addRuntimeSafety("slice sentinel mismatch - floats",
242 \\const std = @import("std");242 \\const std = @import("std");
243 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {243 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
244 \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {244 \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {
245 \\ std.process.exit(126); // good245 \\ std.process.exit(126); // good
246 \\ }246 \\ }
...@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
254254
255 cases.addRuntimeSafety("pointer slice sentinel mismatch",255 cases.addRuntimeSafety("pointer slice sentinel mismatch",
256 \\const std = @import("std");256 \\const std = @import("std");
257 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {257 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
258 \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {258 \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {
259 \\ std.process.exit(126); // good259 \\ std.process.exit(126); // good
260 \\ }260 \\ }
...@@ -269,7 +269,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -269,7 +269,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
269269
270 cases.addRuntimeSafety("slice slice sentinel mismatch",270 cases.addRuntimeSafety("slice slice sentinel mismatch",
271 \\const std = @import("std");271 \\const std = @import("std");
272 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {272 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
273 \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {273 \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {
274 \\ std.process.exit(126); // good274 \\ std.process.exit(126); // good
275 \\ }275 \\ }
...@@ -284,7 +284,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -284,7 +284,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
284284
285 cases.addRuntimeSafety("array slice sentinel mismatch",285 cases.addRuntimeSafety("array slice sentinel mismatch",
286 \\const std = @import("std");286 \\const std = @import("std");
287 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {287 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
288 \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {288 \\ if (std.mem.eql(u8, message, "sentinel mismatch")) {
289 \\ std.process.exit(126); // good289 \\ std.process.exit(126); // good
290 \\ }290 \\ }
...@@ -298,7 +298,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -298,7 +298,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
298298
299 cases.addRuntimeSafety("intToPtr with misaligned address",299 cases.addRuntimeSafety("intToPtr with misaligned address",
300 \\const std = @import("std");300 \\const std = @import("std");
301 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {301 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
302 \\ if (std.mem.eql(u8, message, "incorrect alignment")) {302 \\ if (std.mem.eql(u8, message, "incorrect alignment")) {
303 \\ std.os.exit(126); // good303 \\ std.os.exit(126); // good
304 \\ }304 \\ }
...@@ -311,19 +311,20 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -311,19 +311,20 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
311 );311 );
312312
313 cases.addRuntimeSafety("resuming a non-suspended function which never been suspended",313 cases.addRuntimeSafety("resuming a non-suspended function which never been suspended",
314 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {314 \\const std = @import("std");
315 \\ @import("std").os.exit(126);315 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
316 \\ std.os.exit(126);
316 \\}317 \\}
317 \\fn foo() void {318 \\fn foo() void {
318 \\ var f = async bar(@frame());319 \\ var f = async bar(@frame());
319 \\ @import("std").os.exit(0);320 \\ std.os.exit(0);
320 \\}321 \\}
321 \\322 \\
322 \\fn bar(frame: anyframe) void {323 \\fn bar(frame: anyframe) void {
323 \\ suspend {324 \\ suspend {
324 \\ resume frame;325 \\ resume frame;
325 \\ }326 \\ }
326 \\ @import("std").os.exit(0);327 \\ std.os.exit(0);
327 \\}328 \\}
328 \\329 \\
329 \\pub fn main() void {330 \\pub fn main() void {
...@@ -332,35 +333,37 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -332,35 +333,37 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
332 );333 );
333334
334 cases.addRuntimeSafety("resuming a non-suspended function which has been suspended and resumed",335 cases.addRuntimeSafety("resuming a non-suspended function which has been suspended and resumed",
335 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {336 \\const std = @import("std");
336 \\ @import("std").os.exit(126);337 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
338 \\ std.os.exit(126);
337 \\}339 \\}
338 \\fn foo() void {340 \\fn foo() void {
339 \\ suspend {341 \\ suspend {
340 \\ global_frame = @frame();342 \\ global_frame = @frame();
341 \\ }343 \\ }
342 \\ var f = async bar(@frame());344 \\ var f = async bar(@frame());
343 \\ @import("std").os.exit(0);345 \\ std.os.exit(0);
344 \\}346 \\}
345 \\347 \\
346 \\fn bar(frame: anyframe) void {348 \\fn bar(frame: anyframe) void {
347 \\ suspend {349 \\ suspend {
348 \\ resume frame;350 \\ resume frame;
349 \\ }351 \\ }
350 \\ @import("std").os.exit(0);352 \\ std.os.exit(0);
351 \\}353 \\}
352 \\354 \\
353 \\var global_frame: anyframe = undefined;355 \\var global_frame: anyframe = undefined;
354 \\pub fn main() void {356 \\pub fn main() void {
355 \\ _ = async foo();357 \\ _ = async foo();
356 \\ resume global_frame;358 \\ resume global_frame;
357 \\ @import("std").os.exit(0);359 \\ std.os.exit(0);
358 \\}360 \\}
359 );361 );
360362
361 cases.addRuntimeSafety("nosuspend function call, callee suspends",363 cases.addRuntimeSafety("nosuspend function call, callee suspends",
362 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {364 \\const std = @import("std");
363 \\ @import("std").os.exit(126);365 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
366 \\ std.os.exit(126);
364 \\}367 \\}
365 \\pub fn main() void {368 \\pub fn main() void {
366 \\ _ = nosuspend add(101, 100);369 \\ _ = nosuspend add(101, 100);
...@@ -374,8 +377,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -374,8 +377,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
374 );377 );
375378
376 cases.addRuntimeSafety("awaiting twice",379 cases.addRuntimeSafety("awaiting twice",
377 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {380 \\const std = @import("std");
378 \\ @import("std").os.exit(126);381 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
382 \\ std.os.exit(126);
379 \\}383 \\}
380 \\var frame: anyframe = undefined;384 \\var frame: anyframe = undefined;
381 \\385 \\
...@@ -398,8 +402,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -398,8 +402,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
398 );402 );
399403
400 cases.addRuntimeSafety("@asyncCall with too small a frame",404 cases.addRuntimeSafety("@asyncCall with too small a frame",
401 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {405 \\const std = @import("std");
402 \\ @import("std").os.exit(126);406 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
407 \\ std.os.exit(126);
403 \\}408 \\}
404 \\pub fn main() void {409 \\pub fn main() void {
405 \\ var bytes: [1]u8 align(16) = undefined;410 \\ var bytes: [1]u8 align(16) = undefined;
...@@ -412,8 +417,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -412,8 +417,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
412 );417 );
413418
414 cases.addRuntimeSafety("resuming a function which is awaiting a frame",419 cases.addRuntimeSafety("resuming a function which is awaiting a frame",
415 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {420 \\const std = @import("std");
416 \\ @import("std").os.exit(126);421 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
422 \\ std.os.exit(126);
417 \\}423 \\}
418 \\pub fn main() void {424 \\pub fn main() void {
419 \\ var frame = async first();425 \\ var frame = async first();
...@@ -429,8 +435,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -429,8 +435,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
429 );435 );
430436
431 cases.addRuntimeSafety("resuming a function which is awaiting a call",437 cases.addRuntimeSafety("resuming a function which is awaiting a call",
432 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {438 \\const std = @import("std");
433 \\ @import("std").os.exit(126);439 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
440 \\ std.os.exit(126);
434 \\}441 \\}
435 \\pub fn main() void {442 \\pub fn main() void {
436 \\ var frame = async first();443 \\ var frame = async first();
...@@ -445,8 +452,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -445,8 +452,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
445 );452 );
446453
447 cases.addRuntimeSafety("invalid resume of async function",454 cases.addRuntimeSafety("invalid resume of async function",
448 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {455 \\const std = @import("std");
449 \\ @import("std").os.exit(126);456 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
457 \\ std.os.exit(126);
450 \\}458 \\}
451 \\pub fn main() void {459 \\pub fn main() void {
452 \\ var p = async suspendOnce();460 \\ var p = async suspendOnce();
...@@ -459,8 +467,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -459,8 +467,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
459 );467 );
460468
461 cases.addRuntimeSafety(".? operator on null pointer",469 cases.addRuntimeSafety(".? operator on null pointer",
462 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {470 \\const std = @import("std");
463 \\ @import("std").os.exit(126);471 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
472 \\ std.os.exit(126);
464 \\}473 \\}
465 \\pub fn main() void {474 \\pub fn main() void {
466 \\ var ptr: ?*i32 = null;475 \\ var ptr: ?*i32 = null;
...@@ -469,8 +478,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -469,8 +478,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
469 );478 );
470479
471 cases.addRuntimeSafety(".? operator on C pointer",480 cases.addRuntimeSafety(".? operator on C pointer",
472 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {481 \\const std = @import("std");
473 \\ @import("std").os.exit(126);482 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
483 \\ std.os.exit(126);
474 \\}484 \\}
475 \\pub fn main() void {485 \\pub fn main() void {
476 \\ var ptr: [*c]i32 = null;486 \\ var ptr: [*c]i32 = null;
...@@ -479,8 +489,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -479,8 +489,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
479 );489 );
480490
481 cases.addRuntimeSafety("@intToPtr address zero to non-optional pointer",491 cases.addRuntimeSafety("@intToPtr address zero to non-optional pointer",
482 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {492 \\const std = @import("std");
483 \\ @import("std").os.exit(126);493 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
494 \\ std.os.exit(126);
484 \\}495 \\}
485 \\pub fn main() void {496 \\pub fn main() void {
486 \\ var zero: usize = 0;497 \\ var zero: usize = 0;
...@@ -489,8 +500,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -489,8 +500,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
489 );500 );
490501
491 cases.addRuntimeSafety("@intToPtr address zero to non-optional byte-aligned pointer",502 cases.addRuntimeSafety("@intToPtr address zero to non-optional byte-aligned pointer",
492 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {503 \\const std = @import("std");
493 \\ @import("std").os.exit(126);504 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
505 \\ std.os.exit(126);
494 \\}506 \\}
495 \\pub fn main() void {507 \\pub fn main() void {
496 \\ var zero: usize = 0;508 \\ var zero: usize = 0;
...@@ -499,8 +511,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -499,8 +511,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
499 );511 );
500512
501 cases.addRuntimeSafety("pointer casting null to non-optional pointer",513 cases.addRuntimeSafety("pointer casting null to non-optional pointer",
502 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {514 \\const std = @import("std");
503 \\ @import("std").os.exit(126);515 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
516 \\ std.os.exit(126);
504 \\}517 \\}
505 \\pub fn main() void {518 \\pub fn main() void {
506 \\ var c_ptr: [*c]u8 = 0;519 \\ var c_ptr: [*c]u8 = 0;
...@@ -509,8 +522,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -509,8 +522,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
509 );522 );
510523
511 cases.addRuntimeSafety("@intToEnum - no matching tag value",524 cases.addRuntimeSafety("@intToEnum - no matching tag value",
512 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {525 \\const std = @import("std");
513 \\ @import("std").os.exit(126);526 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
527 \\ std.os.exit(126);
514 \\}528 \\}
515 \\const Foo = enum {529 \\const Foo = enum {
516 \\ A,530 \\ A,
...@@ -527,8 +541,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -527,8 +541,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
527 );541 );
528542
529 cases.addRuntimeSafety("@floatToInt cannot fit - negative to unsigned",543 cases.addRuntimeSafety("@floatToInt cannot fit - negative to unsigned",
530 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {544 \\const std = @import("std");
531 \\ @import("std").os.exit(126);545 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
546 \\ std.os.exit(126);
532 \\}547 \\}
533 \\pub fn main() void {548 \\pub fn main() void {
534 \\ baz(bar(-1.1));549 \\ baz(bar(-1.1));
...@@ -540,8 +555,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -540,8 +555,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
540 );555 );
541556
542 cases.addRuntimeSafety("@floatToInt cannot fit - negative out of range",557 cases.addRuntimeSafety("@floatToInt cannot fit - negative out of range",
543 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {558 \\const std = @import("std");
544 \\ @import("std").os.exit(126);559 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
560 \\ std.os.exit(126);
545 \\}561 \\}
546 \\pub fn main() void {562 \\pub fn main() void {
547 \\ baz(bar(-129.1));563 \\ baz(bar(-129.1));
...@@ -553,8 +569,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -553,8 +569,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
553 );569 );
554570
555 cases.addRuntimeSafety("@floatToInt cannot fit - positive out of range",571 cases.addRuntimeSafety("@floatToInt cannot fit - positive out of range",
556 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {572 \\const std = @import("std");
557 \\ @import("std").os.exit(126);573 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
574 \\ std.os.exit(126);
558 \\}575 \\}
559 \\pub fn main() void {576 \\pub fn main() void {
560 \\ baz(bar(256.2));577 \\ baz(bar(256.2));
...@@ -566,8 +583,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -566,8 +583,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
566 );583 );
567584
568 cases.addRuntimeSafety("calling panic",585 cases.addRuntimeSafety("calling panic",
569 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {586 \\const std = @import("std");
570 \\ @import("std").os.exit(126);587 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
588 \\ std.os.exit(126);
571 \\}589 \\}
572 \\pub fn main() void {590 \\pub fn main() void {
573 \\ @panic("oh no");591 \\ @panic("oh no");
...@@ -575,8 +593,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -575,8 +593,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
575 );593 );
576594
577 cases.addRuntimeSafety("out of bounds slice access",595 cases.addRuntimeSafety("out of bounds slice access",
578 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {596 \\const std = @import("std");
579 \\ @import("std").os.exit(126);597 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
598 \\ std.os.exit(126);
580 \\}599 \\}
581 \\pub fn main() void {600 \\pub fn main() void {
582 \\ const a = [_]i32{1, 2, 3, 4};601 \\ const a = [_]i32{1, 2, 3, 4};
...@@ -589,8 +608,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -589,8 +608,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
589 );608 );
590609
591 cases.addRuntimeSafety("integer addition overflow",610 cases.addRuntimeSafety("integer addition overflow",
592 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {611 \\const std = @import("std");
593 \\ @import("std").os.exit(126);612 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
613 \\ std.os.exit(126);
594 \\}614 \\}
595 \\pub fn main() !void {615 \\pub fn main() !void {
596 \\ const x = add(65530, 10);616 \\ const x = add(65530, 10);
...@@ -602,63 +622,68 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -602,63 +622,68 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
602 );622 );
603623
604 cases.addRuntimeSafety("vector integer addition overflow",624 cases.addRuntimeSafety("vector integer addition overflow",
605 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {625 \\const std = @import("std");
606 \\ @import("std").os.exit(126);626 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
627 \\ std.os.exit(126);
607 \\}628 \\}
608 \\pub fn main() void {629 \\pub fn main() void {
609 \\ var a: @import("std").meta.Vector(4, i32) = [_]i32{ 1, 2, 2147483643, 4 };630 \\ var a: std.meta.Vector(4, i32) = [_]i32{ 1, 2, 2147483643, 4 };
610 \\ var b: @import("std").meta.Vector(4, i32) = [_]i32{ 5, 6, 7, 8 };631 \\ var b: std.meta.Vector(4, i32) = [_]i32{ 5, 6, 7, 8 };
611 \\ const x = add(a, b);632 \\ const x = add(a, b);
612 \\}633 \\}
613 \\fn add(a: @import("std").meta.Vector(4, i32), b: @import("std").meta.Vector(4, i32)) @import("std").meta.Vector(4, i32) {634 \\fn add(a: std.meta.Vector(4, i32), b: std.meta.Vector(4, i32)) std.meta.Vector(4, i32) {
614 \\ return a + b;635 \\ return a + b;
615 \\}636 \\}
616 );637 );
617638
618 cases.addRuntimeSafety("vector integer subtraction overflow",639 cases.addRuntimeSafety("vector integer subtraction overflow",
619 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {640 \\const std = @import("std");
620 \\ @import("std").os.exit(126);641 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
642 \\ std.os.exit(126);
621 \\}643 \\}
622 \\pub fn main() void {644 \\pub fn main() void {
623 \\ var a: @import("std").meta.Vector(4, u32) = [_]u32{ 1, 2, 8, 4 };645 \\ var a: std.meta.Vector(4, u32) = [_]u32{ 1, 2, 8, 4 };
624 \\ var b: @import("std").meta.Vector(4, u32) = [_]u32{ 5, 6, 7, 8 };646 \\ var b: std.meta.Vector(4, u32) = [_]u32{ 5, 6, 7, 8 };
625 \\ const x = sub(b, a);647 \\ const x = sub(b, a);
626 \\}648 \\}
627 \\fn sub(a: @import("std").meta.Vector(4, u32), b: @import("std").meta.Vector(4, u32)) @import("std").meta.Vector(4, u32) {649 \\fn sub(a: std.meta.Vector(4, u32), b: std.meta.Vector(4, u32)) std.meta.Vector(4, u32) {
628 \\ return a - b;650 \\ return a - b;
629 \\}651 \\}
630 );652 );
631653
632 cases.addRuntimeSafety("vector integer multiplication overflow",654 cases.addRuntimeSafety("vector integer multiplication overflow",
633 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {655 \\const std = @import("std");
634 \\ @import("std").os.exit(126);656 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
657 \\ std.os.exit(126);
635 \\}658 \\}
636 \\pub fn main() void {659 \\pub fn main() void {
637 \\ var a: @import("std").meta.Vector(4, u8) = [_]u8{ 1, 2, 200, 4 };660 \\ var a: std.meta.Vector(4, u8) = [_]u8{ 1, 2, 200, 4 };
638 \\ var b: @import("std").meta.Vector(4, u8) = [_]u8{ 5, 6, 2, 8 };661 \\ var b: std.meta.Vector(4, u8) = [_]u8{ 5, 6, 2, 8 };
639 \\ const x = mul(b, a);662 \\ const x = mul(b, a);
640 \\}663 \\}
641 \\fn mul(a: @import("std").meta.Vector(4, u8), b: @import("std").meta.Vector(4, u8)) @import("std").meta.Vector(4, u8) {664 \\fn mul(a: std.meta.Vector(4, u8), b: std.meta.Vector(4, u8)) std.meta.Vector(4, u8) {
642 \\ return a * b;665 \\ return a * b;
643 \\}666 \\}
644 );667 );
645668
646 cases.addRuntimeSafety("vector integer negation overflow",669 cases.addRuntimeSafety("vector integer negation overflow",
647 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {670 \\const std = @import("std");
648 \\ @import("std").os.exit(126);671 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
672 \\ std.os.exit(126);
649 \\}673 \\}
650 \\pub fn main() void {674 \\pub fn main() void {
651 \\ var a: @import("std").meta.Vector(4, i16) = [_]i16{ 1, -32768, 200, 4 };675 \\ var a: std.meta.Vector(4, i16) = [_]i16{ 1, -32768, 200, 4 };
652 \\ const x = neg(a);676 \\ const x = neg(a);
653 \\}677 \\}
654 \\fn neg(a: @import("std").meta.Vector(4, i16)) @import("std").meta.Vector(4, i16) {678 \\fn neg(a: std.meta.Vector(4, i16)) std.meta.Vector(4, i16) {
655 \\ return -a;679 \\ return -a;
656 \\}680 \\}
657 );681 );
658682
659 cases.addRuntimeSafety("integer subtraction overflow",683 cases.addRuntimeSafety("integer subtraction overflow",
660 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {684 \\const std = @import("std");
661 \\ @import("std").os.exit(126);685 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
686 \\ std.os.exit(126);
662 \\}687 \\}
663 \\pub fn main() !void {688 \\pub fn main() !void {
664 \\ const x = sub(10, 20);689 \\ const x = sub(10, 20);
...@@ -670,8 +695,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -670,8 +695,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
670 );695 );
671696
672 cases.addRuntimeSafety("integer multiplication overflow",697 cases.addRuntimeSafety("integer multiplication overflow",
673 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {698 \\const std = @import("std");
674 \\ @import("std").os.exit(126);699 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
700 \\ std.os.exit(126);
675 \\}701 \\}
676 \\pub fn main() !void {702 \\pub fn main() !void {
677 \\ const x = mul(300, 6000);703 \\ const x = mul(300, 6000);
...@@ -683,8 +709,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -683,8 +709,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
683 );709 );
684710
685 cases.addRuntimeSafety("integer negation overflow",711 cases.addRuntimeSafety("integer negation overflow",
686 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {712 \\const std = @import("std");
687 \\ @import("std").os.exit(126);713 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
714 \\ std.os.exit(126);
688 \\}715 \\}
689 \\pub fn main() !void {716 \\pub fn main() !void {
690 \\ const x = neg(-32768);717 \\ const x = neg(-32768);
...@@ -696,8 +723,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -696,8 +723,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
696 );723 );
697724
698 cases.addRuntimeSafety("signed integer division overflow",725 cases.addRuntimeSafety("signed integer division overflow",
699 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {726 \\const std = @import("std");
700 \\ @import("std").os.exit(126);727 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
728 \\ std.os.exit(126);
701 \\}729 \\}
702 \\pub fn main() !void {730 \\pub fn main() !void {
703 \\ const x = div(-32768, -1);731 \\ const x = div(-32768, -1);
...@@ -709,23 +737,25 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -709,23 +737,25 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
709 );737 );
710738
711 cases.addRuntimeSafety("signed integer division overflow - vectors",739 cases.addRuntimeSafety("signed integer division overflow - vectors",
712 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {740 \\const std = @import("std");
713 \\ @import("std").os.exit(126);741 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
742 \\ std.os.exit(126);
714 \\}743 \\}
715 \\pub fn main() !void {744 \\pub fn main() !void {
716 \\ var a: @import("std").meta.Vector(4, i16) = [_]i16{ 1, 2, -32768, 4 };745 \\ var a: std.meta.Vector(4, i16) = [_]i16{ 1, 2, -32768, 4 };
717 \\ var b: @import("std").meta.Vector(4, i16) = [_]i16{ 1, 2, -1, 4 };746 \\ var b: std.meta.Vector(4, i16) = [_]i16{ 1, 2, -1, 4 };
718 \\ const x = div(a, b);747 \\ const x = div(a, b);
719 \\ if (x[2] == 32767) return error.Whatever;748 \\ if (x[2] == 32767) return error.Whatever;
720 \\}749 \\}
721 \\fn div(a: @import("std").meta.Vector(4, i16), b: @import("std").meta.Vector(4, i16)) @import("std").meta.Vector(4, i16) {750 \\fn div(a: std.meta.Vector(4, i16), b: std.meta.Vector(4, i16)) std.meta.Vector(4, i16) {
722 \\ return @divTrunc(a, b);751 \\ return @divTrunc(a, b);
723 \\}752 \\}
724 );753 );
725754
726 cases.addRuntimeSafety("signed shift left overflow",755 cases.addRuntimeSafety("signed shift left overflow",
727 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {756 \\const std = @import("std");
728 \\ @import("std").os.exit(126);757 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
758 \\ std.os.exit(126);
729 \\}759 \\}
730 \\pub fn main() !void {760 \\pub fn main() !void {
731 \\ const x = shl(-16385, 1);761 \\ const x = shl(-16385, 1);
...@@ -737,8 +767,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -737,8 +767,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
737 );767 );
738768
739 cases.addRuntimeSafety("unsigned shift left overflow",769 cases.addRuntimeSafety("unsigned shift left overflow",
740 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {770 \\const std = @import("std");
741 \\ @import("std").os.exit(126);771 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
772 \\ std.os.exit(126);
742 \\}773 \\}
743 \\pub fn main() !void {774 \\pub fn main() !void {
744 \\ const x = shl(0b0010111111111111, 3);775 \\ const x = shl(0b0010111111111111, 3);
...@@ -750,8 +781,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -750,8 +781,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
750 );781 );
751782
752 cases.addRuntimeSafety("signed shift right overflow",783 cases.addRuntimeSafety("signed shift right overflow",
753 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {784 \\const std = @import("std");
754 \\ @import("std").os.exit(126);785 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
786 \\ std.os.exit(126);
755 \\}787 \\}
756 \\pub fn main() !void {788 \\pub fn main() !void {
757 \\ const x = shr(-16385, 1);789 \\ const x = shr(-16385, 1);
...@@ -763,8 +795,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -763,8 +795,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
763 );795 );
764796
765 cases.addRuntimeSafety("unsigned shift right overflow",797 cases.addRuntimeSafety("unsigned shift right overflow",
766 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {798 \\const std = @import("std");
767 \\ @import("std").os.exit(126);799 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
800 \\ std.os.exit(126);
768 \\}801 \\}
769 \\pub fn main() !void {802 \\pub fn main() !void {
770 \\ const x = shr(0b0010111111111111, 3);803 \\ const x = shr(0b0010111111111111, 3);
...@@ -776,8 +809,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -776,8 +809,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
776 );809 );
777810
778 cases.addRuntimeSafety("integer division by zero",811 cases.addRuntimeSafety("integer division by zero",
779 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {812 \\const std = @import("std");
780 \\ @import("std").os.exit(126);813 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
814 \\ std.os.exit(126);
781 \\}815 \\}
782 \\pub fn main() void {816 \\pub fn main() void {
783 \\ const x = div0(999, 0);817 \\ const x = div0(999, 0);
...@@ -788,22 +822,24 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -788,22 +822,24 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
788 );822 );
789823
790 cases.addRuntimeSafety("integer division by zero - vectors",824 cases.addRuntimeSafety("integer division by zero - vectors",
791 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {825 \\const std = @import("std");
792 \\ @import("std").os.exit(126);826 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
827 \\ std.os.exit(126);
793 \\}828 \\}
794 \\pub fn main() void {829 \\pub fn main() void {
795 \\ var a: @import("std").meta.Vector(4, i32) = [4]i32{111, 222, 333, 444};830 \\ var a: std.meta.Vector(4, i32) = [4]i32{111, 222, 333, 444};
796 \\ var b: @import("std").meta.Vector(4, i32) = [4]i32{111, 0, 333, 444};831 \\ var b: std.meta.Vector(4, i32) = [4]i32{111, 0, 333, 444};
797 \\ const x = div0(a, b);832 \\ const x = div0(a, b);
798 \\}833 \\}
799 \\fn div0(a: @import("std").meta.Vector(4, i32), b: @import("std").meta.Vector(4, i32)) @import("std").meta.Vector(4, i32) {834 \\fn div0(a: std.meta.Vector(4, i32), b: std.meta.Vector(4, i32)) std.meta.Vector(4, i32) {
800 \\ return @divTrunc(a, b);835 \\ return @divTrunc(a, b);
801 \\}836 \\}
802 );837 );
803838
804 cases.addRuntimeSafety("exact division failure",839 cases.addRuntimeSafety("exact division failure",
805 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {840 \\const std = @import("std");
806 \\ @import("std").os.exit(126);841 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
842 \\ std.os.exit(126);
807 \\}843 \\}
808 \\pub fn main() !void {844 \\pub fn main() !void {
809 \\ const x = divExact(10, 3);845 \\ const x = divExact(10, 3);
...@@ -815,15 +851,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -815,15 +851,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
815 );851 );
816852
817 cases.addRuntimeSafety("exact division failure - vectors",853 cases.addRuntimeSafety("exact division failure - vectors",
818 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {854 \\const std = @import("std");
819 \\ @import("std").os.exit(126);855 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
856 \\ std.os.exit(126);
820 \\}857 \\}
821 \\pub fn main() !void {858 \\pub fn main() !void {
822 \\ var a: @import("std").meta.Vector(4, i32) = [4]i32{111, 222, 333, 444};859 \\ var a: std.meta.Vector(4, i32) = [4]i32{111, 222, 333, 444};
823 \\ var b: @import("std").meta.Vector(4, i32) = [4]i32{111, 222, 333, 441};860 \\ var b: std.meta.Vector(4, i32) = [4]i32{111, 222, 333, 441};
824 \\ const x = divExact(a, b);861 \\ const x = divExact(a, b);
825 \\}862 \\}
826 \\fn divExact(a: @import("std").meta.Vector(4, i32), b: @import("std").meta.Vector(4, i32)) @import("std").meta.Vector(4, i32) {863 \\fn divExact(a: std.meta.Vector(4, i32), b: std.meta.Vector(4, i32)) std.meta.Vector(4, i32) {
827 \\ return @divExact(a, b);864 \\ return @divExact(a, b);
828 \\}865 \\}
829 );866 );
...@@ -843,8 +880,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -843,8 +880,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
843 );880 );
844881
845 cases.addRuntimeSafety("value does not fit in shortening cast",882 cases.addRuntimeSafety("value does not fit in shortening cast",
846 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {883 \\const std = @import("std");
847 \\ @import("std").os.exit(126);884 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
885 \\ std.os.exit(126);
848 \\}886 \\}
849 \\pub fn main() !void {887 \\pub fn main() !void {
850 \\ const x = shorten_cast(200);888 \\ const x = shorten_cast(200);
...@@ -856,8 +894,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -856,8 +894,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
856 );894 );
857895
858 cases.addRuntimeSafety("value does not fit in shortening cast - u0",896 cases.addRuntimeSafety("value does not fit in shortening cast - u0",
859 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {897 \\const std = @import("std");
860 \\ @import("std").os.exit(126);898 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
899 \\ std.os.exit(126);
861 \\}900 \\}
862 \\pub fn main() !void {901 \\pub fn main() !void {
863 \\ const x = shorten_cast(1);902 \\ const x = shorten_cast(1);
...@@ -869,8 +908,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -869,8 +908,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
869 );908 );
870909
871 cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer",910 cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer",
872 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {911 \\const std = @import("std");
873 \\ @import("std").os.exit(126);912 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
913 \\ std.os.exit(126);
874 \\}914 \\}
875 \\pub fn main() !void {915 \\pub fn main() !void {
876 \\ const x = unsigned_cast(-10);916 \\ const x = unsigned_cast(-10);
...@@ -882,8 +922,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -882,8 +922,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
882 );922 );
883923
884 cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer - widening",924 cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer - widening",
885 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {925 \\const std = @import("std");
886 \\ @import("std").os.exit(126);926 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
927 \\ std.os.exit(126);
887 \\}928 \\}
888 \\pub fn main() void {929 \\pub fn main() void {
889 \\ var value: c_short = -1;930 \\ var value: c_short = -1;
...@@ -892,8 +933,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -892,8 +933,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
892 );933 );
893934
894 cases.addRuntimeSafety("unsigned integer not fitting in cast to signed integer - same bit count",935 cases.addRuntimeSafety("unsigned integer not fitting in cast to signed integer - same bit count",
895 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {936 \\const std = @import("std");
896 \\ @import("std").os.exit(126);937 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
938 \\ std.os.exit(126);
897 \\}939 \\}
898 \\pub fn main() void {940 \\pub fn main() void {
899 \\ var value: u8 = 245;941 \\ var value: u8 = 245;
...@@ -902,11 +944,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -902,11 +944,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
902 );944 );
903945
904 cases.addRuntimeSafety("unwrap error",946 cases.addRuntimeSafety("unwrap error",
905 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {947 \\const std = @import("std");
906 \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) {948 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
907 \\ @import("std").os.exit(126); // good949 \\ if (std.mem.eql(u8, message, "attempt to unwrap error: Whatever")) {
950 \\ std.os.exit(126); // good
908 \\ }951 \\ }
909 \\ @import("std").os.exit(0); // test failed952 \\ std.os.exit(0); // test failed
910 \\}953 \\}
911 \\pub fn main() void {954 \\pub fn main() void {
912 \\ bar() catch unreachable;955 \\ bar() catch unreachable;
...@@ -917,8 +960,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -917,8 +960,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
917 );960 );
918961
919 cases.addRuntimeSafety("cast integer to global error and no code matches",962 cases.addRuntimeSafety("cast integer to global error and no code matches",
920 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {963 \\const std = @import("std");
921 \\ @import("std").os.exit(126);964 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
965 \\ std.os.exit(126);
922 \\}966 \\}
923 \\pub fn main() void {967 \\pub fn main() void {
924 \\ bar(9999) catch {};968 \\ bar(9999) catch {};
...@@ -929,8 +973,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -929,8 +973,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
929 );973 );
930974
931 cases.addRuntimeSafety("@errSetCast error not present in destination",975 cases.addRuntimeSafety("@errSetCast error not present in destination",
932 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {976 \\const std = @import("std");
933 \\ @import("std").os.exit(126);977 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
978 \\ std.os.exit(126);
934 \\}979 \\}
935 \\const Set1 = error{A, B};980 \\const Set1 = error{A, B};
936 \\const Set2 = error{A, C};981 \\const Set2 = error{A, C};
...@@ -960,8 +1005,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -960,8 +1005,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
960 );1005 );
9611006
962 cases.addRuntimeSafety("bad union field access",1007 cases.addRuntimeSafety("bad union field access",
963 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {1008 \\const std = @import("std");
964 \\ @import("std").os.exit(126);1009 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
1010 \\ std.os.exit(126);
965 \\}1011 \\}
966 \\1012 \\
967 \\const Foo = union {1013 \\const Foo = union {
...@@ -983,8 +1029,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -983,8 +1029,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
983 // but we still emit a safety check to ensure the integer was 0 and thus1029 // but we still emit a safety check to ensure the integer was 0 and thus
984 // did not truncate information.1030 // did not truncate information.
985 cases.addRuntimeSafety("@intCast to u0",1031 cases.addRuntimeSafety("@intCast to u0",
986 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {1032 \\const std = @import("std");
987 \\ @import("std").os.exit(126);1033 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
1034 \\ std.os.exit(126);
988 \\}1035 \\}
989 \\1036 \\
990 \\pub fn main() void {1037 \\pub fn main() void {
...@@ -1001,7 +1048,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -1001,7 +1048,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
1001 cases.addRuntimeSafety("error return trace across suspend points",1048 cases.addRuntimeSafety("error return trace across suspend points",
1002 \\const std = @import("std");1049 \\const std = @import("std");
1003 \\1050 \\
1004 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {1051 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
1005 \\ std.os.exit(126);1052 \\ std.os.exit(126);
1006 \\}1053 \\}
1007 \\1054 \\
...@@ -1035,8 +1082,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -1035,8 +1082,9 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
1035 // Slicing a C pointer returns a non-allowzero slice, thus we need to emit1082 // Slicing a C pointer returns a non-allowzero slice, thus we need to emit
1036 // a safety check to ensure the pointer is not null.1083 // a safety check to ensure the pointer is not null.
1037 cases.addRuntimeSafety("slicing null C pointer",1084 cases.addRuntimeSafety("slicing null C pointer",
1038 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {1085 \\const std = @import("std");
1039 \\ @import("std").os.exit(126);1086 \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
1087 \\ std.os.exit(126);
1040 \\}1088 \\}
1041 \\1089 \\
1042 \\pub fn main() void {1090 \\pub fn main() void {
test/stage1/behavior.zig deleted-145
...@@ -1,145 +0,0 @@
1const builtin = @import("builtin");
2
3comptime {
4 _ = @import("behavior/align.zig");
5 _ = @import("behavior/alignof.zig");
6 _ = @import("behavior/array.zig");
7 if (builtin.os.tag != .wasi) {
8 _ = @import("behavior/asm.zig");
9 _ = @import("behavior/async_fn.zig");
10 }
11 _ = @import("behavior/atomics.zig");
12 _ = @import("behavior/await_struct.zig");
13 _ = @import("behavior/bit_shifting.zig");
14 _ = @import("behavior/bitcast.zig");
15 _ = @import("behavior/bitreverse.zig");
16 _ = @import("behavior/bool.zig");
17 _ = @import("behavior/bugs/1025.zig");
18 _ = @import("behavior/bugs/1076.zig");
19 _ = @import("behavior/bugs/1111.zig");
20 _ = @import("behavior/bugs/1120.zig");
21 _ = @import("behavior/bugs/1277.zig");
22 _ = @import("behavior/bugs/1310.zig");
23 _ = @import("behavior/bugs/1322.zig");
24 _ = @import("behavior/bugs/1381.zig");
25 _ = @import("behavior/bugs/1421.zig");
26 _ = @import("behavior/bugs/1442.zig");
27 _ = @import("behavior/bugs/1486.zig");
28 _ = @import("behavior/bugs/1500.zig");
29 _ = @import("behavior/bugs/1607.zig");
30 _ = @import("behavior/bugs/1735.zig");
31 _ = @import("behavior/bugs/1741.zig");
32 _ = @import("behavior/bugs/1851.zig");
33 _ = @import("behavior/bugs/1914.zig");
34 _ = @import("behavior/bugs/2006.zig");
35 _ = @import("behavior/bugs/2114.zig");
36 _ = @import("behavior/bugs/2346.zig");
37 _ = @import("behavior/bugs/2578.zig");
38 _ = @import("behavior/bugs/2692.zig");
39 _ = @import("behavior/bugs/2889.zig");
40 _ = @import("behavior/bugs/3007.zig");
41 _ = @import("behavior/bugs/3046.zig");
42 _ = @import("behavior/bugs/3112.zig");
43 _ = @import("behavior/bugs/3367.zig");
44 _ = @import("behavior/bugs/3384.zig");
45 _ = @import("behavior/bugs/3586.zig");
46 _ = @import("behavior/bugs/3742.zig");
47 _ = @import("behavior/bugs/4328.zig");
48 _ = @import("behavior/bugs/4560.zig");
49 _ = @import("behavior/bugs/4769_a.zig");
50 _ = @import("behavior/bugs/4769_b.zig");
51 _ = @import("behavior/bugs/4769_c.zig");
52 _ = @import("behavior/bugs/4954.zig");
53 _ = @import("behavior/bugs/5398.zig");
54 _ = @import("behavior/bugs/5413.zig");
55 _ = @import("behavior/bugs/5474.zig");
56 _ = @import("behavior/bugs/5487.zig");
57 _ = @import("behavior/bugs/6456.zig");
58 _ = @import("behavior/bugs/6781.zig");
59 _ = @import("behavior/bugs/6850.zig");
60 _ = @import("behavior/bugs/7027.zig");
61 _ = @import("behavior/bugs/7047.zig");
62 _ = @import("behavior/bugs/7003.zig");
63 _ = @import("behavior/bugs/7250.zig");
64 _ = @import("behavior/bugs/394.zig");
65 _ = @import("behavior/bugs/421.zig");
66 _ = @import("behavior/bugs/529.zig");
67 _ = @import("behavior/bugs/624.zig");
68 _ = @import("behavior/bugs/655.zig");
69 _ = @import("behavior/bugs/656.zig");
70 _ = @import("behavior/bugs/679.zig");
71 _ = @import("behavior/bugs/704.zig");
72 _ = @import("behavior/bugs/718.zig");
73 _ = @import("behavior/bugs/726.zig");
74 _ = @import("behavior/bugs/828.zig");
75 _ = @import("behavior/bugs/920.zig");
76 _ = @import("behavior/byteswap.zig");
77 _ = @import("behavior/byval_arg_var.zig");
78 _ = @import("behavior/call.zig");
79 _ = @import("behavior/cast.zig");
80 _ = @import("behavior/const_slice_child.zig");
81 _ = @import("behavior/defer.zig");
82 _ = @import("behavior/enum.zig");
83 _ = @import("behavior/enum_with_members.zig");
84 _ = @import("behavior/error.zig");
85 _ = @import("behavior/eval.zig");
86 _ = @import("behavior/field_parent_ptr.zig");
87 _ = @import("behavior/floatop.zig");
88 _ = @import("behavior/fn.zig");
89 _ = @import("behavior/fn_in_struct_in_comptime.zig");
90 _ = @import("behavior/fn_delegation.zig");
91 _ = @import("behavior/for.zig");
92 _ = @import("behavior/generics.zig");
93 _ = @import("behavior/hasdecl.zig");
94 _ = @import("behavior/hasfield.zig");
95 _ = @import("behavior/if.zig");
96 _ = @import("behavior/import.zig");
97 _ = @import("behavior/incomplete_struct_param_tld.zig");
98 _ = @import("behavior/inttoptr.zig");
99 _ = @import("behavior/ir_block_deps.zig");
100 _ = @import("behavior/math.zig");
101 _ = @import("behavior/merge_error_sets.zig");
102 _ = @import("behavior/misc.zig");
103 _ = @import("behavior/muladd.zig");
104 _ = @import("behavior/namespace_depends_on_compile_var.zig");
105 _ = @import("behavior/null.zig");
106 _ = @import("behavior/optional.zig");
107 _ = @import("behavior/pointers.zig");
108 _ = @import("behavior/popcount.zig");
109 _ = @import("behavior/ptrcast.zig");
110 _ = @import("behavior/pub_enum.zig");
111 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
112 _ = @import("behavior/reflection.zig");
113 _ = @import("behavior/shuffle.zig");
114 _ = @import("behavior/sizeof_and_typeof.zig");
115 _ = @import("behavior/slice.zig");
116 _ = @import("behavior/slice_sentinel_comptime.zig");
117 _ = @import("behavior/struct.zig");
118 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
119 _ = @import("behavior/struct_contains_slice_of_itself.zig");
120 _ = @import("behavior/switch.zig");
121 _ = @import("behavior/switch_prong_err_enum.zig");
122 _ = @import("behavior/switch_prong_implicit_cast.zig");
123 _ = @import("behavior/syntax.zig");
124 _ = @import("behavior/this.zig");
125 _ = @import("behavior/truncate.zig");
126 _ = @import("behavior/try.zig");
127 _ = @import("behavior/tuple.zig");
128 _ = @import("behavior/type.zig");
129 _ = @import("behavior/type_info.zig");
130 _ = @import("behavior/typename.zig");
131 _ = @import("behavior/undefined.zig");
132 _ = @import("behavior/underscore.zig");
133 _ = @import("behavior/union.zig");
134 _ = @import("behavior/usingnamespace.zig");
135 _ = @import("behavior/var_args.zig");
136 _ = @import("behavior/vector.zig");
137 _ = @import("behavior/void.zig");
138 if (builtin.arch == .wasm32) {
139 _ = @import("behavior/wasm.zig");
140 }
141 _ = @import("behavior/while.zig");
142 _ = @import("behavior/widening.zig");
143 _ = @import("behavior/src.zig");
144 _ = @import("behavior/translate_c_macros.zig");
145}
test/stage1/behavior/align.zig deleted-349
...@@ -1,349 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const builtin = @import("builtin");
4
5var foo: u8 align(4) = 100;
6
7test "global variable alignment" {
8 comptime try expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4);
9 comptime try expect(@TypeOf(&foo) == *align(4) u8);
10 {
11 const slice = @as(*[1]u8, &foo)[0..];
12 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
13 }
14 {
15 var runtime_zero: usize = 0;
16 const slice = @as(*[1]u8, &foo)[runtime_zero..];
17 comptime try expect(@TypeOf(slice) == []align(4) u8);
18 }
19}
20
21fn derp() align(@sizeOf(usize) * 2) i32 {
22 return 1234;
23}
24fn noop1() align(1) void {}
25fn noop4() align(4) void {}
26
27test "function alignment" {
28 // function alignment is a compile error on wasm32/wasm64
29 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
30
31 try expect(derp() == 1234);
32 try expect(@TypeOf(noop1) == fn () align(1) void);
33 try expect(@TypeOf(noop4) == fn () align(4) void);
34 noop1();
35 noop4();
36}
37
38var baz: packed struct {
39 a: u32,
40 b: u32,
41} = undefined;
42
43test "packed struct alignment" {
44 try expect(@TypeOf(&baz.b) == *align(1) u32);
45}
46
47const blah: packed struct {
48 a: u3,
49 b: u3,
50 c: u2,
51} = undefined;
52
53test "bit field alignment" {
54 try expect(@TypeOf(&blah.b) == *align(1:3:1) const u3);
55}
56
57test "default alignment allows unspecified in type syntax" {
58 try expect(*u32 == *align(@alignOf(u32)) u32);
59}
60
61test "implicitly decreasing pointer alignment" {
62 const a: u32 align(4) = 3;
63 const b: u32 align(8) = 4;
64 try expect(addUnaligned(&a, &b) == 7);
65}
66
67fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
68 return a.* + b.*;
69}
70
71test "implicitly decreasing slice alignment" {
72 const a: u32 align(4) = 3;
73 const b: u32 align(8) = 4;
74 try expect(addUnalignedSlice(@as(*const [1]u32, &a)[0..], @as(*const [1]u32, &b)[0..]) == 7);
75}
76fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
77 return a[0] + b[0];
78}
79
80test "specifying alignment allows pointer cast" {
81 try testBytesAlign(0x33);
82}
83fn testBytesAlign(b: u8) !void {
84 var bytes align(4) = [_]u8{
85 b,
86 b,
87 b,
88 b,
89 };
90 const ptr = @ptrCast(*u32, &bytes[0]);
91 try expect(ptr.* == 0x33333333);
92}
93
94test "@alignCast pointers" {
95 var x: u32 align(4) = 1;
96 expectsOnly1(&x);
97 try expect(x == 2);
98}
99fn expectsOnly1(x: *align(1) u32) void {
100 expects4(@alignCast(4, x));
101}
102fn expects4(x: *align(4) u32) void {
103 x.* += 1;
104}
105
106test "@alignCast slices" {
107 var array align(4) = [_]u32{
108 1,
109 1,
110 };
111 const slice = array[0..];
112 sliceExpectsOnly1(slice);
113 try expect(slice[0] == 2);
114}
115fn sliceExpectsOnly1(slice: []align(1) u32) void {
116 sliceExpects4(@alignCast(4, slice));
117}
118fn sliceExpects4(slice: []align(4) u32) void {
119 slice[0] += 1;
120}
121
122test "implicitly decreasing fn alignment" {
123 // function alignment is a compile error on wasm32/wasm64
124 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
125
126 try testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
127 try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
128}
129
130fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) !void {
131 try expect(ptr() == answer);
132}
133
134fn alignedSmall() align(8) i32 {
135 return 1234;
136}
137fn alignedBig() align(16) i32 {
138 return 5678;
139}
140
141test "@alignCast functions" {
142 // function alignment is a compile error on wasm32/wasm64
143 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
144 if (builtin.arch == .thumb) return error.SkipZigTest;
145
146 try expect(fnExpectsOnly1(simple4) == 0x19);
147}
148fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
149 return fnExpects4(@alignCast(4, ptr));
150}
151fn fnExpects4(ptr: fn () align(4) i32) i32 {
152 return ptr();
153}
154fn simple4() align(4) i32 {
155 return 0x19;
156}
157
158test "generic function with align param" {
159 // function alignment is a compile error on wasm32/wasm64
160 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
161 if (builtin.arch == .thumb) return error.SkipZigTest;
162
163 try expect(whyWouldYouEverDoThis(1) == 0x1);
164 try expect(whyWouldYouEverDoThis(4) == 0x1);
165 try expect(whyWouldYouEverDoThis(8) == 0x1);
166}
167
168fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
169 return 0x1;
170}
171
172test "@ptrCast preserves alignment of bigger source" {
173 var x: u32 align(16) = 1234;
174 const ptr = @ptrCast(*u8, &x);
175 try expect(@TypeOf(ptr) == *align(16) u8);
176}
177
178test "runtime known array index has best alignment possible" {
179 // take full advantage of over-alignment
180 var array align(4) = [_]u8{ 1, 2, 3, 4 };
181 try expect(@TypeOf(&array[0]) == *align(4) u8);
182 try expect(@TypeOf(&array[1]) == *u8);
183 try expect(@TypeOf(&array[2]) == *align(2) u8);
184 try expect(@TypeOf(&array[3]) == *u8);
185
186 // because align is too small but we still figure out to use 2
187 var bigger align(2) = [_]u64{ 1, 2, 3, 4 };
188 try expect(@TypeOf(&bigger[0]) == *align(2) u64);
189 try expect(@TypeOf(&bigger[1]) == *align(2) u64);
190 try expect(@TypeOf(&bigger[2]) == *align(2) u64);
191 try expect(@TypeOf(&bigger[3]) == *align(2) u64);
192
193 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
194 var smaller align(2) = [_]u32{ 1, 2, 3, 4 };
195 var runtime_zero: usize = 0;
196 comptime try expect(@TypeOf(smaller[runtime_zero..]) == []align(2) u32);
197 comptime try expect(@TypeOf(smaller[runtime_zero..].ptr) == [*]align(2) u32);
198 try testIndex(smaller[runtime_zero..].ptr, 0, *align(2) u32);
199 try testIndex(smaller[runtime_zero..].ptr, 1, *align(2) u32);
200 try testIndex(smaller[runtime_zero..].ptr, 2, *align(2) u32);
201 try testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32);
202
203 // has to use ABI alignment because index known at runtime only
204 try testIndex2(array[runtime_zero..].ptr, 0, *u8);
205 try testIndex2(array[runtime_zero..].ptr, 1, *u8);
206 try testIndex2(array[runtime_zero..].ptr, 2, *u8);
207 try testIndex2(array[runtime_zero..].ptr, 3, *u8);
208}
209fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) !void {
210 comptime try expect(@TypeOf(&smaller[index]) == T);
211}
212fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {
213 comptime try expect(@TypeOf(&ptr[index]) == T);
214}
215
216test "alignstack" {
217 try expect(fnWithAlignedStack() == 1234);
218}
219
220fn fnWithAlignedStack() i32 {
221 @setAlignStack(256);
222 return 1234;
223}
224
225test "alignment of structs" {
226 try expect(@alignOf(struct {
227 a: i32,
228 b: *i32,
229 }) == @alignOf(usize));
230}
231
232test "alignment of function with c calling convention" {
233 var runtime_nothing = nothing;
234 const casted1 = @ptrCast(*const u8, runtime_nothing);
235 const casted2 = @ptrCast(fn () callconv(.C) void, casted1);
236 casted2();
237}
238
239fn nothing() callconv(.C) void {}
240
241test "return error union with 128-bit integer" {
242 try expect(3 == try give());
243}
244fn give() anyerror!u128 {
245 return 3;
246}
247
248test "alignment of >= 128-bit integer type" {
249 try expect(@alignOf(u128) == 16);
250 try expect(@alignOf(u129) == 16);
251}
252
253test "alignment of struct with 128-bit field" {
254 try expect(@alignOf(struct {
255 x: u128,
256 }) == 16);
257
258 comptime {
259 try expect(@alignOf(struct {
260 x: u128,
261 }) == 16);
262 }
263}
264
265test "size of extern struct with 128-bit field" {
266 try expect(@sizeOf(extern struct {
267 x: u128,
268 y: u8,
269 }) == 32);
270
271 comptime {
272 try expect(@sizeOf(extern struct {
273 x: u128,
274 y: u8,
275 }) == 32);
276 }
277}
278
279const DefaultAligned = struct {
280 nevermind: u32,
281 badguy: i128,
282};
283
284test "read 128-bit field from default aligned struct in stack memory" {
285 var default_aligned = DefaultAligned{
286 .nevermind = 1,
287 .badguy = 12,
288 };
289 try expect((@ptrToInt(&default_aligned.badguy) % 16) == 0);
290 try expect(12 == default_aligned.badguy);
291}
292
293var default_aligned_global = DefaultAligned{
294 .nevermind = 1,
295 .badguy = 12,
296};
297
298test "read 128-bit field from default aligned struct in global memory" {
299 try expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0);
300 try expect(12 == default_aligned_global.badguy);
301}
302
303test "struct field explicit alignment" {
304 const S = struct {
305 const Node = struct {
306 next: *Node,
307 massive_byte: u8 align(64),
308 };
309 };
310
311 var node: S.Node = undefined;
312 node.massive_byte = 100;
313 try expect(node.massive_byte == 100);
314 comptime try expect(@TypeOf(&node.massive_byte) == *align(64) u8);
315 try expect(@ptrToInt(&node.massive_byte) % 64 == 0);
316}
317
318test "align(@alignOf(T)) T does not force resolution of T" {
319 const S = struct {
320 const A = struct {
321 a: *align(@alignOf(A)) A,
322 };
323 fn doTheTest() void {
324 suspend {
325 resume @frame();
326 }
327 _ = bar(@Frame(doTheTest));
328 }
329 fn bar(comptime T: type) *align(@alignOf(T)) T {
330 ok = true;
331 return undefined;
332 }
333
334 var ok = false;
335 };
336 _ = async S.doTheTest();
337 try expect(S.ok);
338}
339
340test "align(N) on functions" {
341 // function alignment is a compile error on wasm32/wasm64
342 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
343 if (builtin.arch == .thumb) return error.SkipZigTest;
344
345 try expect((@ptrToInt(overaligned_fn) & (0x1000 - 1)) == 0);
346}
347fn overaligned_fn() align(0x1000) i32 {
348 return 42;
349}
test/stage1/behavior/alignof.zig deleted-38
...@@ -1,38 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const Foo = struct {
7 x: u32,
8 y: u32,
9 z: u32,
10};
11
12test "@alignOf(T) before referencing T" {
13 comptime try expect(@alignOf(Foo) != maxInt(usize));
14 if (builtin.arch == builtin.Arch.x86_64) {
15 comptime try expect(@alignOf(Foo) == 4);
16 }
17}
18
19test "comparison of @alignOf(T) against zero" {
20 {
21 const T = struct { x: u32 };
22 try expect(!(@alignOf(T) == 0));
23 try expect(@alignOf(T) != 0);
24 try expect(!(@alignOf(T) < 0));
25 try expect(!(@alignOf(T) <= 0));
26 try expect(@alignOf(T) > 0);
27 try expect(@alignOf(T) >= 0);
28 }
29 {
30 const T = struct {};
31 try expect(@alignOf(T) == 0);
32 try expect(!(@alignOf(T) != 0));
33 try expect(!(@alignOf(T) < 0));
34 try expect(@alignOf(T) <= 0);
35 try expect(!(@alignOf(T) > 0));
36 try expect(@alignOf(T) >= 0);
37 }
38}
test/stage1/behavior/array.zig deleted-489
...@@ -1,489 +0,0 @@
1const std = @import("std");
2const testing = std.testing;
3const mem = std.mem;
4const expect = testing.expect;
5const expectEqual = testing.expectEqual;
6
7test "arrays" {
8 var array: [5]u32 = undefined;
9
10 var i: u32 = 0;
11 while (i < 5) {
12 array[i] = i + 1;
13 i = array[i];
14 }
15
16 i = 0;
17 var accumulator = @as(u32, 0);
18 while (i < 5) {
19 accumulator += array[i];
20
21 i += 1;
22 }
23
24 try expect(accumulator == 15);
25 try expect(getArrayLen(&array) == 5);
26}
27fn getArrayLen(a: []const u32) usize {
28 return a.len;
29}
30
31test "array with sentinels" {
32 const S = struct {
33 fn doTheTest(is_ct: bool) !void {
34 if (is_ct) {
35 var zero_sized: [0:0xde]u8 = [_:0xde]u8{};
36 // Disabled at runtime because of
37 // https://github.com/ziglang/zig/issues/4372
38 try expectEqual(@as(u8, 0xde), zero_sized[0]);
39 var reinterpreted = @ptrCast(*[1]u8, &zero_sized);
40 try expectEqual(@as(u8, 0xde), reinterpreted[0]);
41 }
42 var arr: [3:0x55]u8 = undefined;
43 // Make sure the sentinel pointer is pointing after the last element
44 if (!is_ct) {
45 const sentinel_ptr = @ptrToInt(&arr[3]);
46 const last_elem_ptr = @ptrToInt(&arr[2]);
47 try expectEqual(@as(usize, 1), sentinel_ptr - last_elem_ptr);
48 }
49 // Make sure the sentinel is writeable
50 arr[3] = 0x55;
51 }
52 };
53
54 try S.doTheTest(false);
55 comptime try S.doTheTest(true);
56}
57
58test "void arrays" {
59 var array: [4]void = undefined;
60 array[0] = void{};
61 array[1] = array[2];
62 try expect(@sizeOf(@TypeOf(array)) == 0);
63 try expect(array.len == 4);
64}
65
66test "array literal" {
67 const hex_mult = [_]u16{
68 4096,
69 256,
70 16,
71 1,
72 };
73
74 try expect(hex_mult.len == 4);
75 try expect(hex_mult[1] == 256);
76}
77
78test "array dot len const expr" {
79 try expect(comptime x: {
80 break :x some_array.len == 4;
81 });
82}
83
84const ArrayDotLenConstExpr = struct {
85 y: [some_array.len]u8,
86};
87const some_array = [_]u8{
88 0,
89 1,
90 2,
91 3,
92};
93
94test "nested arrays" {
95 const array_of_strings = [_][]const u8{
96 "hello",
97 "this",
98 "is",
99 "my",
100 "thing",
101 };
102 for (array_of_strings) |s, i| {
103 if (i == 0) try expect(mem.eql(u8, s, "hello"));
104 if (i == 1) try expect(mem.eql(u8, s, "this"));
105 if (i == 2) try expect(mem.eql(u8, s, "is"));
106 if (i == 3) try expect(mem.eql(u8, s, "my"));
107 if (i == 4) try expect(mem.eql(u8, s, "thing"));
108 }
109}
110
111var s_array: [8]Sub = undefined;
112const Sub = struct {
113 b: u8,
114};
115const Str = struct {
116 a: []Sub,
117};
118test "set global var array via slice embedded in struct" {
119 var s = Str{ .a = s_array[0..] };
120
121 s.a[0].b = 1;
122 s.a[1].b = 2;
123 s.a[2].b = 3;
124
125 try expect(s_array[0].b == 1);
126 try expect(s_array[1].b == 2);
127 try expect(s_array[2].b == 3);
128}
129
130test "array literal with specified size" {
131 var array = [2]u8{
132 1,
133 2,
134 };
135 try expect(array[0] == 1);
136 try expect(array[1] == 2);
137}
138
139test "array len field" {
140 var arr = [4]u8{ 0, 0, 0, 0 };
141 var ptr = &arr;
142 try expect(arr.len == 4);
143 comptime try expect(arr.len == 4);
144 try expect(ptr.len == 4);
145 comptime try expect(ptr.len == 4);
146}
147
148test "single-item pointer to array indexing and slicing" {
149 try testSingleItemPtrArrayIndexSlice();
150 comptime try testSingleItemPtrArrayIndexSlice();
151}
152
153fn testSingleItemPtrArrayIndexSlice() !void {
154 {
155 var array: [4]u8 = "aaaa".*;
156 doSomeMangling(&array);
157 try expect(mem.eql(u8, "azya", &array));
158 }
159 {
160 var array = "aaaa".*;
161 doSomeMangling(&array);
162 try expect(mem.eql(u8, "azya", &array));
163 }
164}
165
166fn doSomeMangling(array: *[4]u8) void {
167 array[1] = 'z';
168 array[2..3][0] = 'y';
169}
170
171test "implicit cast single-item pointer" {
172 try testImplicitCastSingleItemPtr();
173 comptime try testImplicitCastSingleItemPtr();
174}
175
176fn testImplicitCastSingleItemPtr() !void {
177 var byte: u8 = 100;
178 const slice = @as(*[1]u8, &byte)[0..];
179 slice[0] += 1;
180 try expect(byte == 101);
181}
182
183fn testArrayByValAtComptime(b: [2]u8) u8 {
184 return b[0];
185}
186
187test "comptime evalutating function that takes array by value" {
188 const arr = [_]u8{ 0, 1 };
189 _ = comptime testArrayByValAtComptime(arr);
190 _ = comptime testArrayByValAtComptime(arr);
191}
192
193test "implicit comptime in array type size" {
194 var arr: [plusOne(10)]bool = undefined;
195 try expect(arr.len == 11);
196}
197
198fn plusOne(x: u32) u32 {
199 return x + 1;
200}
201
202test "runtime initialize array elem and then implicit cast to slice" {
203 var two: i32 = 2;
204 const x: []const i32 = &[_]i32{two};
205 try expect(x[0] == 2);
206}
207
208test "array literal as argument to function" {
209 const S = struct {
210 fn entry(two: i32) !void {
211 try foo(&[_]i32{
212 1,
213 2,
214 3,
215 });
216 try foo(&[_]i32{
217 1,
218 two,
219 3,
220 });
221 try foo2(true, &[_]i32{
222 1,
223 2,
224 3,
225 });
226 try foo2(true, &[_]i32{
227 1,
228 two,
229 3,
230 });
231 }
232 fn foo(x: []const i32) !void {
233 try expect(x[0] == 1);
234 try expect(x[1] == 2);
235 try expect(x[2] == 3);
236 }
237 fn foo2(trash: bool, x: []const i32) !void {
238 try expect(trash);
239 try expect(x[0] == 1);
240 try expect(x[1] == 2);
241 try expect(x[2] == 3);
242 }
243 };
244 try S.entry(2);
245 comptime try S.entry(2);
246}
247
248test "double nested array to const slice cast in array literal" {
249 const S = struct {
250 fn entry(two: i32) !void {
251 const cases = [_][]const []const i32{
252 &[_][]const i32{&[_]i32{1}},
253 &[_][]const i32{&[_]i32{ 2, 3 }},
254 &[_][]const i32{
255 &[_]i32{4},
256 &[_]i32{ 5, 6, 7 },
257 },
258 };
259 try check(&cases);
260
261 const cases2 = [_][]const i32{
262 &[_]i32{1},
263 &[_]i32{ two, 3 },
264 };
265 try expect(cases2.len == 2);
266 try expect(cases2[0].len == 1);
267 try expect(cases2[0][0] == 1);
268 try expect(cases2[1].len == 2);
269 try expect(cases2[1][0] == 2);
270 try expect(cases2[1][1] == 3);
271
272 const cases3 = [_][]const []const i32{
273 &[_][]const i32{&[_]i32{1}},
274 &[_][]const i32{&[_]i32{ two, 3 }},
275 &[_][]const i32{
276 &[_]i32{4},
277 &[_]i32{ 5, 6, 7 },
278 },
279 };
280 try check(&cases3);
281 }
282
283 fn check(cases: []const []const []const i32) !void {
284 try expect(cases.len == 3);
285 try expect(cases[0].len == 1);
286 try expect(cases[0][0].len == 1);
287 try expect(cases[0][0][0] == 1);
288 try expect(cases[1].len == 1);
289 try expect(cases[1][0].len == 2);
290 try expect(cases[1][0][0] == 2);
291 try expect(cases[1][0][1] == 3);
292 try expect(cases[2].len == 2);
293 try expect(cases[2][0].len == 1);
294 try expect(cases[2][0][0] == 4);
295 try expect(cases[2][1].len == 3);
296 try expect(cases[2][1][0] == 5);
297 try expect(cases[2][1][1] == 6);
298 try expect(cases[2][1][2] == 7);
299 }
300 };
301 try S.entry(2);
302 comptime try S.entry(2);
303}
304
305test "read/write through global variable array of struct fields initialized via array mult" {
306 const S = struct {
307 fn doTheTest() !void {
308 try expect(storage[0].term == 1);
309 storage[0] = MyStruct{ .term = 123 };
310 try expect(storage[0].term == 123);
311 }
312
313 pub const MyStruct = struct {
314 term: usize,
315 };
316
317 var storage: [1]MyStruct = [_]MyStruct{MyStruct{ .term = 1 }} ** 1;
318 };
319 try S.doTheTest();
320}
321
322test "implicit cast zero sized array ptr to slice" {
323 {
324 var b = "".*;
325 const c: []const u8 = &b;
326 try expect(c.len == 0);
327 }
328 {
329 var b: [0]u8 = "".*;
330 const c: []const u8 = &b;
331 try expect(c.len == 0);
332 }
333}
334
335test "anonymous list literal syntax" {
336 const S = struct {
337 fn doTheTest() !void {
338 var array: [4]u8 = .{ 1, 2, 3, 4 };
339 try expect(array[0] == 1);
340 try expect(array[1] == 2);
341 try expect(array[2] == 3);
342 try expect(array[3] == 4);
343 }
344 };
345 try S.doTheTest();
346 comptime try S.doTheTest();
347}
348
349test "anonymous literal in array" {
350 const S = struct {
351 const Foo = struct {
352 a: usize = 2,
353 b: usize = 4,
354 };
355 fn doTheTest() !void {
356 var array: [2]Foo = .{
357 .{ .a = 3 },
358 .{ .b = 3 },
359 };
360 try expect(array[0].a == 3);
361 try expect(array[0].b == 4);
362 try expect(array[1].a == 2);
363 try expect(array[1].b == 3);
364 }
365 };
366 try S.doTheTest();
367 comptime try S.doTheTest();
368}
369
370test "access the null element of a null terminated array" {
371 const S = struct {
372 fn doTheTest() !void {
373 var array: [4:0]u8 = .{ 'a', 'o', 'e', 'u' };
374 try expect(array[4] == 0);
375 var len: usize = 4;
376 try expect(array[len] == 0);
377 }
378 };
379 try S.doTheTest();
380 comptime try S.doTheTest();
381}
382
383test "type deduction for array subscript expression" {
384 const S = struct {
385 fn doTheTest() !void {
386 var array = [_]u8{ 0x55, 0xAA };
387 var v0 = true;
388 try expectEqual(@as(u8, 0xAA), array[if (v0) 1 else 0]);
389 var v1 = false;
390 try expectEqual(@as(u8, 0x55), array[if (v1) 1 else 0]);
391 }
392 };
393 try S.doTheTest();
394 comptime try S.doTheTest();
395}
396
397test "sentinel element count towards the ABI size calculation" {
398 const S = struct {
399 fn doTheTest() !void {
400 const T = packed struct {
401 fill_pre: u8 = 0x55,
402 data: [0:0]u8 = undefined,
403 fill_post: u8 = 0xAA,
404 };
405 var x = T{};
406 var as_slice = mem.asBytes(&x);
407 try expectEqual(@as(usize, 3), as_slice.len);
408 try expectEqual(@as(u8, 0x55), as_slice[0]);
409 try expectEqual(@as(u8, 0xAA), as_slice[2]);
410 }
411 };
412
413 try S.doTheTest();
414 comptime try S.doTheTest();
415}
416
417test "zero-sized array with recursive type definition" {
418 const U = struct {
419 fn foo(comptime T: type, comptime n: usize) type {
420 return struct {
421 s: [n]T,
422 x: usize = n,
423 };
424 }
425 };
426
427 const S = struct {
428 list: U.foo(@This(), 0),
429 };
430
431 var t: S = .{ .list = .{ .s = undefined } };
432 try expectEqual(@as(usize, 0), t.list.x);
433}
434
435test "type coercion of anon struct literal to array" {
436 const S = struct {
437 const U = union {
438 a: u32,
439 b: bool,
440 c: []const u8,
441 };
442
443 fn doTheTest() !void {
444 var x1: u8 = 42;
445 const t1 = .{ x1, 56, 54 };
446 var arr1: [3]u8 = t1;
447 try expect(arr1[0] == 42);
448 try expect(arr1[1] == 56);
449 try expect(arr1[2] == 54);
450
451 var x2: U = .{ .a = 42 };
452 const t2 = .{ x2, .{ .b = true }, .{ .c = "hello" } };
453 var arr2: [3]U = t2;
454 try expect(arr2[0].a == 42);
455 try expect(arr2[1].b == true);
456 try expect(mem.eql(u8, arr2[2].c, "hello"));
457 }
458 };
459 try S.doTheTest();
460 comptime try S.doTheTest();
461}
462
463test "type coercion of pointer to anon struct literal to pointer to array" {
464 const S = struct {
465 const U = union {
466 a: u32,
467 b: bool,
468 c: []const u8,
469 };
470
471 fn doTheTest() !void {
472 var x1: u8 = 42;
473 const t1 = &.{ x1, 56, 54 };
474 var arr1: *const [3]u8 = t1;
475 try expect(arr1[0] == 42);
476 try expect(arr1[1] == 56);
477 try expect(arr1[2] == 54);
478
479 var x2: U = .{ .a = 42 };
480 const t2 = &.{ x2, .{ .b = true }, .{ .c = "hello" } };
481 var arr2: *const [3]U = t2;
482 try expect(arr2[0].a == 42);
483 try expect(arr2[1].b == true);
484 try expect(mem.eql(u8, arr2[2].c, "hello"));
485 }
486 };
487 try S.doTheTest();
488 comptime try S.doTheTest();
489}
test/stage1/behavior/asm.zig deleted-109
...@@ -1,109 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const is_x86_64_linux = std.Target.current.cpu.arch == .x86_64 and std.Target.current.os.tag == .linux;
5
6comptime {
7 if (is_x86_64_linux) {
8 asm (
9 \\.globl this_is_my_alias;
10 \\.type this_is_my_alias, @function;
11 \\.set this_is_my_alias, derp;
12 );
13 }
14}
15
16test "module level assembly" {
17 if (is_x86_64_linux) {
18 try expect(this_is_my_alias() == 1234);
19 }
20}
21
22test "output constraint modifiers" {
23 // This is only testing compilation.
24 var a: u32 = 3;
25 asm volatile (""
26 : [_] "=m,r" (a)
27 :
28 : ""
29 );
30 asm volatile (""
31 : [_] "=r,m" (a)
32 :
33 : ""
34 );
35}
36
37test "alternative constraints" {
38 // Make sure we allow commas as a separator for alternative constraints.
39 var a: u32 = 3;
40 asm volatile (""
41 : [_] "=r,m" (a)
42 : [_] "r,m" (a)
43 : ""
44 );
45}
46
47test "sized integer/float in asm input" {
48 asm volatile (""
49 :
50 : [_] "m" (@as(usize, 3))
51 : ""
52 );
53 asm volatile (""
54 :
55 : [_] "m" (@as(i15, -3))
56 : ""
57 );
58 asm volatile (""
59 :
60 : [_] "m" (@as(u3, 3))
61 : ""
62 );
63 asm volatile (""
64 :
65 : [_] "m" (@as(i3, 3))
66 : ""
67 );
68 asm volatile (""
69 :
70 : [_] "m" (@as(u121, 3))
71 : ""
72 );
73 asm volatile (""
74 :
75 : [_] "m" (@as(i121, 3))
76 : ""
77 );
78 asm volatile (""
79 :
80 : [_] "m" (@as(f32, 3.17))
81 : ""
82 );
83 asm volatile (""
84 :
85 : [_] "m" (@as(f64, 3.17))
86 : ""
87 );
88}
89
90test "struct/array/union types as input values" {
91 asm volatile (""
92 :
93 : [_] "m" (@as([1]u32, undefined))
94 ); // fails
95 asm volatile (""
96 :
97 : [_] "m" (@as(struct { x: u32, y: u8 }, undefined))
98 ); // fails
99 asm volatile (""
100 :
101 : [_] "m" (@as(union { x: u32, y: u8 }, undefined))
102 ); // fails
103}
104
105extern fn this_is_my_alias() i32;
106
107export fn derp() i32 {
108 return 1234;
109}
test/stage1/behavior/async_fn.zig deleted-1676
...@@ -1,1676 +0,0 @@
1const std = @import("std");
2const builtin = std.builtin;
3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;
5const expectEqualStrings = std.testing.expectEqualStrings;
6const expectError = std.testing.expectError;
7
8var global_x: i32 = 1;
9
10test "simple coroutine suspend and resume" {
11 var frame = async simpleAsyncFn();
12 try expect(global_x == 2);
13 resume frame;
14 try expect(global_x == 3);
15 const af: anyframe->void = &frame;
16 resume frame;
17 try expect(global_x == 4);
18}
19fn simpleAsyncFn() void {
20 global_x += 1;
21 suspend {}
22 global_x += 1;
23 suspend {}
24 global_x += 1;
25}
26
27var global_y: i32 = 1;
28
29test "pass parameter to coroutine" {
30 var p = async simpleAsyncFnWithArg(2);
31 try expect(global_y == 3);
32 resume p;
33 try expect(global_y == 5);
34}
35fn simpleAsyncFnWithArg(delta: i32) void {
36 global_y += delta;
37 suspend {}
38 global_y += delta;
39}
40
41test "suspend at end of function" {
42 const S = struct {
43 var x: i32 = 1;
44
45 fn doTheTest() !void {
46 try expect(x == 1);
47 const p = async suspendAtEnd();
48 try expect(x == 2);
49 }
50
51 fn suspendAtEnd() void {
52 x += 1;
53 suspend {}
54 }
55 };
56 try S.doTheTest();
57}
58
59test "local variable in async function" {
60 const S = struct {
61 var x: i32 = 0;
62
63 fn doTheTest() !void {
64 try expect(x == 0);
65 var p = async add(1, 2);
66 try expect(x == 0);
67 resume p;
68 try expect(x == 0);
69 resume p;
70 try expect(x == 0);
71 resume p;
72 try expect(x == 3);
73 }
74
75 fn add(a: i32, b: i32) void {
76 var accum: i32 = 0;
77 suspend {}
78 accum += a;
79 suspend {}
80 accum += b;
81 suspend {}
82 x = accum;
83 }
84 };
85 try S.doTheTest();
86}
87
88test "calling an inferred async function" {
89 const S = struct {
90 var x: i32 = 1;
91 var other_frame: *@Frame(other) = undefined;
92
93 fn doTheTest() !void {
94 _ = async first();
95 try expect(x == 1);
96 resume other_frame.*;
97 try expect(x == 2);
98 }
99
100 fn first() void {
101 other();
102 }
103 fn other() void {
104 other_frame = @frame();
105 suspend {}
106 x += 1;
107 }
108 };
109 try S.doTheTest();
110}
111
112test "@frameSize" {
113 if (builtin.arch == .thumb or builtin.arch == .thumbeb)
114 return error.SkipZigTest;
115
116 const S = struct {
117 fn doTheTest() !void {
118 {
119 var ptr = @ptrCast(fn (i32) callconv(.Async) void, other);
120 const size = @frameSize(ptr);
121 try expect(size == @sizeOf(@Frame(other)));
122 }
123 {
124 var ptr = @ptrCast(fn () callconv(.Async) void, first);
125 const size = @frameSize(ptr);
126 try expect(size == @sizeOf(@Frame(first)));
127 }
128 }
129
130 fn first() void {
131 other(1);
132 }
133 fn other(param: i32) void {
134 var local: i32 = undefined;
135 suspend {}
136 }
137 };
138 try S.doTheTest();
139}
140
141test "coroutine suspend, resume" {
142 const S = struct {
143 var frame: anyframe = undefined;
144
145 fn doTheTest() !void {
146 _ = async amain();
147 seq('d');
148 resume frame;
149 seq('h');
150
151 try expect(std.mem.eql(u8, &points, "abcdefgh"));
152 }
153
154 fn amain() void {
155 seq('a');
156 var f = async testAsyncSeq();
157 seq('c');
158 await f;
159 seq('g');
160 }
161
162 fn testAsyncSeq() void {
163 defer seq('f');
164
165 seq('b');
166 suspend {
167 frame = @frame();
168 }
169 seq('e');
170 }
171 var points = [_]u8{'x'} ** "abcdefgh".len;
172 var index: usize = 0;
173
174 fn seq(c: u8) void {
175 points[index] = c;
176 index += 1;
177 }
178 };
179 try S.doTheTest();
180}
181
182test "coroutine suspend with block" {
183 const p = async testSuspendBlock();
184 try expect(!global_result);
185 resume a_promise;
186 try expect(global_result);
187}
188
189var a_promise: anyframe = undefined;
190var global_result = false;
191fn testSuspendBlock() callconv(.Async) void {
192 suspend {
193 comptime expect(@TypeOf(@frame()) == *@Frame(testSuspendBlock)) catch unreachable;
194 a_promise = @frame();
195 }
196
197 // Test to make sure that @frame() works as advertised (issue #1296)
198 // var our_handle: anyframe = @frame();
199 expect(a_promise == @as(anyframe, @frame())) catch @panic("test failed");
200
201 global_result = true;
202}
203
204var await_a_promise: anyframe = undefined;
205var await_final_result: i32 = 0;
206
207test "coroutine await" {
208 await_seq('a');
209 var p = async await_amain();
210 await_seq('f');
211 resume await_a_promise;
212 await_seq('i');
213 try expect(await_final_result == 1234);
214 try expect(std.mem.eql(u8, &await_points, "abcdefghi"));
215}
216fn await_amain() callconv(.Async) void {
217 await_seq('b');
218 var p = async await_another();
219 await_seq('e');
220 await_final_result = await p;
221 await_seq('h');
222}
223fn await_another() callconv(.Async) i32 {
224 await_seq('c');
225 suspend {
226 await_seq('d');
227 await_a_promise = @frame();
228 }
229 await_seq('g');
230 return 1234;
231}
232
233var await_points = [_]u8{0} ** "abcdefghi".len;
234var await_seq_index: usize = 0;
235
236fn await_seq(c: u8) void {
237 await_points[await_seq_index] = c;
238 await_seq_index += 1;
239}
240
241var early_final_result: i32 = 0;
242
243test "coroutine await early return" {
244 early_seq('a');
245 var p = async early_amain();
246 early_seq('f');
247 try expect(early_final_result == 1234);
248 try expect(std.mem.eql(u8, &early_points, "abcdef"));
249}
250fn early_amain() callconv(.Async) void {
251 early_seq('b');
252 var p = async early_another();
253 early_seq('d');
254 early_final_result = await p;
255 early_seq('e');
256}
257fn early_another() callconv(.Async) i32 {
258 early_seq('c');
259 return 1234;
260}
261
262var early_points = [_]u8{0} ** "abcdef".len;
263var early_seq_index: usize = 0;
264
265fn early_seq(c: u8) void {
266 early_points[early_seq_index] = c;
267 early_seq_index += 1;
268}
269
270test "async function with dot syntax" {
271 const S = struct {
272 var y: i32 = 1;
273 fn foo() callconv(.Async) void {
274 y += 1;
275 suspend {}
276 }
277 };
278 const p = async S.foo();
279 try expect(S.y == 2);
280}
281
282test "async fn pointer in a struct field" {
283 var data: i32 = 1;
284 const Foo = struct {
285 bar: fn (*i32) callconv(.Async) void,
286 };
287 var foo = Foo{ .bar = simpleAsyncFn2 };
288 var bytes: [64]u8 align(16) = undefined;
289 const f = @asyncCall(&bytes, {}, foo.bar, .{&data});
290 comptime try expect(@TypeOf(f) == anyframe->void);
291 try expect(data == 2);
292 resume f;
293 try expect(data == 4);
294 _ = async doTheAwait(f);
295 try expect(data == 4);
296}
297
298fn doTheAwait(f: anyframe->void) void {
299 await f;
300}
301fn simpleAsyncFn2(y: *i32) callconv(.Async) void {
302 defer y.* += 2;
303 y.* += 1;
304 suspend {}
305}
306
307test "@asyncCall with return type" {
308 const Foo = struct {
309 bar: fn () callconv(.Async) i32,
310
311 var global_frame: anyframe = undefined;
312 fn middle() callconv(.Async) i32 {
313 return afunc();
314 }
315
316 fn afunc() i32 {
317 global_frame = @frame();
318 suspend {}
319 return 1234;
320 }
321 };
322 var foo = Foo{ .bar = Foo.middle };
323 var bytes: [150]u8 align(16) = undefined;
324 var aresult: i32 = 0;
325 _ = @asyncCall(&bytes, &aresult, foo.bar, .{});
326 try expect(aresult == 0);
327 resume Foo.global_frame;
328 try expect(aresult == 1234);
329}
330
331test "async fn with inferred error set" {
332 const S = struct {
333 var global_frame: anyframe = undefined;
334
335 fn doTheTest() !void {
336 var frame: [1]@Frame(middle) = undefined;
337 var fn_ptr = middle;
338 var result: @typeInfo(@typeInfo(@TypeOf(fn_ptr)).Fn.return_type.?).ErrorUnion.error_set!void = undefined;
339 _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr, .{});
340 resume global_frame;
341 try std.testing.expectError(error.Fail, result);
342 }
343 fn middle() callconv(.Async) !void {
344 var f = async middle2();
345 return await f;
346 }
347
348 fn middle2() !void {
349 return failing();
350 }
351
352 fn failing() !void {
353 global_frame = @frame();
354 suspend {}
355 return error.Fail;
356 }
357 };
358 try S.doTheTest();
359}
360
361test "error return trace across suspend points - early return" {
362 const p = nonFailing();
363 resume p;
364 const p2 = async printTrace(p);
365}
366
367test "error return trace across suspend points - async return" {
368 const p = nonFailing();
369 const p2 = async printTrace(p);
370 resume p;
371}
372
373fn nonFailing() (anyframe->anyerror!void) {
374 const Static = struct {
375 var frame: @Frame(suspendThenFail) = undefined;
376 };
377 Static.frame = async suspendThenFail();
378 return &Static.frame;
379}
380fn suspendThenFail() callconv(.Async) anyerror!void {
381 suspend {}
382 return error.Fail;
383}
384fn printTrace(p: anyframe->(anyerror!void)) callconv(.Async) void {
385 (await p) catch |e| {
386 std.testing.expect(e == error.Fail) catch @panic("test failure");
387 if (@errorReturnTrace()) |trace| {
388 expect(trace.index == 1) catch @panic("test failure");
389 } else switch (builtin.mode) {
390 .Debug, .ReleaseSafe => @panic("expected return trace"),
391 .ReleaseFast, .ReleaseSmall => {},
392 }
393 };
394}
395
396test "break from suspend" {
397 var my_result: i32 = 1;
398 const p = async testBreakFromSuspend(&my_result);
399 try std.testing.expect(my_result == 2);
400}
401fn testBreakFromSuspend(my_result: *i32) callconv(.Async) void {
402 suspend {
403 resume @frame();
404 }
405 my_result.* += 1;
406 suspend {}
407 my_result.* += 1;
408}
409
410test "heap allocated async function frame" {
411 const S = struct {
412 var x: i32 = 42;
413
414 fn doTheTest() !void {
415 const frame = try std.testing.allocator.create(@Frame(someFunc));
416 defer std.testing.allocator.destroy(frame);
417
418 try expect(x == 42);
419 frame.* = async someFunc();
420 try expect(x == 43);
421 resume frame;
422 try expect(x == 44);
423 }
424
425 fn someFunc() void {
426 x += 1;
427 suspend {}
428 x += 1;
429 }
430 };
431 try S.doTheTest();
432}
433
434test "async function call return value" {
435 const S = struct {
436 var frame: anyframe = undefined;
437 var pt = Point{ .x = 10, .y = 11 };
438
439 fn doTheTest() !void {
440 try expectEqual(pt.x, 10);
441 try expectEqual(pt.y, 11);
442 _ = async first();
443 try expectEqual(pt.x, 10);
444 try expectEqual(pt.y, 11);
445 resume frame;
446 try expectEqual(pt.x, 1);
447 try expectEqual(pt.y, 2);
448 }
449
450 fn first() void {
451 pt = second(1, 2);
452 }
453
454 fn second(x: i32, y: i32) Point {
455 return other(x, y);
456 }
457
458 fn other(x: i32, y: i32) Point {
459 frame = @frame();
460 suspend {}
461 return Point{
462 .x = x,
463 .y = y,
464 };
465 }
466
467 const Point = struct {
468 x: i32,
469 y: i32,
470 };
471 };
472 try S.doTheTest();
473}
474
475test "suspension points inside branching control flow" {
476 const S = struct {
477 var result: i32 = 10;
478
479 fn doTheTest() !void {
480 try expect(10 == result);
481 var frame = async func(true);
482 try expect(10 == result);
483 resume frame;
484 try expect(11 == result);
485 resume frame;
486 try expect(12 == result);
487 resume frame;
488 try expect(13 == result);
489 }
490
491 fn func(b: bool) void {
492 while (b) {
493 suspend {}
494 result += 1;
495 }
496 }
497 };
498 try S.doTheTest();
499}
500
501test "call async function which has struct return type" {
502 const S = struct {
503 var frame: anyframe = undefined;
504
505 fn doTheTest() void {
506 _ = async atest();
507 resume frame;
508 }
509
510 fn atest() void {
511 const result = func();
512 expect(result.x == 5) catch @panic("test failed");
513 expect(result.y == 6) catch @panic("test failed");
514 }
515
516 const Point = struct {
517 x: usize,
518 y: usize,
519 };
520
521 fn func() Point {
522 suspend {
523 frame = @frame();
524 }
525 return Point{
526 .x = 5,
527 .y = 6,
528 };
529 }
530 };
531 S.doTheTest();
532}
533
534test "pass string literal to async function" {
535 const S = struct {
536 var frame: anyframe = undefined;
537 var ok: bool = false;
538
539 fn doTheTest() !void {
540 _ = async hello("hello");
541 resume frame;
542 try expect(ok);
543 }
544
545 fn hello(msg: []const u8) void {
546 frame = @frame();
547 suspend {}
548 expectEqualStrings("hello", msg) catch @panic("test failed");
549 ok = true;
550 }
551 };
552 try S.doTheTest();
553}
554
555test "await inside an errdefer" {
556 const S = struct {
557 var frame: anyframe = undefined;
558
559 fn doTheTest() !void {
560 _ = async amainWrap();
561 resume frame;
562 }
563
564 fn amainWrap() !void {
565 var foo = async func();
566 errdefer await foo;
567 return error.Bad;
568 }
569
570 fn func() void {
571 frame = @frame();
572 suspend {}
573 }
574 };
575 try S.doTheTest();
576}
577
578test "try in an async function with error union and non-zero-bit payload" {
579 const S = struct {
580 var frame: anyframe = undefined;
581 var ok = false;
582
583 fn doTheTest() !void {
584 _ = async amain();
585 resume frame;
586 try expect(ok);
587 }
588
589 fn amain() void {
590 std.testing.expectError(error.Bad, theProblem()) catch @panic("test failed");
591 ok = true;
592 }
593
594 fn theProblem() ![]u8 {
595 frame = @frame();
596 suspend {}
597 const result = try other();
598 return result;
599 }
600
601 fn other() ![]u8 {
602 return error.Bad;
603 }
604 };
605 try S.doTheTest();
606}
607
608test "returning a const error from async function" {
609 const S = struct {
610 var frame: anyframe = undefined;
611 var ok = false;
612
613 fn doTheTest() !void {
614 _ = async amain();
615 resume frame;
616 try expect(ok);
617 }
618
619 fn amain() !void {
620 var download_frame = async fetchUrl(10, "a string");
621 const download_text = try await download_frame;
622
623 @panic("should not get here");
624 }
625
626 fn fetchUrl(unused: i32, url: []const u8) ![]u8 {
627 frame = @frame();
628 suspend {}
629 ok = true;
630 return error.OutOfMemory;
631 }
632 };
633 try S.doTheTest();
634}
635
636test "async/await typical usage" {
637 inline for ([_]bool{ false, true }) |b1| {
638 inline for ([_]bool{ false, true }) |b2| {
639 inline for ([_]bool{ false, true }) |b3| {
640 inline for ([_]bool{ false, true }) |b4| {
641 testAsyncAwaitTypicalUsage(b1, b2, b3, b4).doTheTest();
642 }
643 }
644 }
645 }
646}
647
648fn testAsyncAwaitTypicalUsage(
649 comptime simulate_fail_download: bool,
650 comptime simulate_fail_file: bool,
651 comptime suspend_download: bool,
652 comptime suspend_file: bool,
653) type {
654 return struct {
655 fn doTheTest() void {
656 _ = async amainWrap();
657 if (suspend_file) {
658 resume global_file_frame;
659 }
660 if (suspend_download) {
661 resume global_download_frame;
662 }
663 }
664 fn amainWrap() void {
665 if (amain()) |_| {
666 expect(!simulate_fail_download) catch @panic("test failure");
667 expect(!simulate_fail_file) catch @panic("test failure");
668 } else |e| switch (e) {
669 error.NoResponse => expect(simulate_fail_download) catch @panic("test failure"),
670 error.FileNotFound => expect(simulate_fail_file) catch @panic("test failure"),
671 else => @panic("test failure"),
672 }
673 }
674
675 fn amain() !void {
676 const allocator = std.testing.allocator;
677 var download_frame = async fetchUrl(allocator, "https://example.com/");
678 var download_awaited = false;
679 errdefer if (!download_awaited) {
680 if (await download_frame) |x| allocator.free(x) else |_| {}
681 };
682
683 var file_frame = async readFile(allocator, "something.txt");
684 var file_awaited = false;
685 errdefer if (!file_awaited) {
686 if (await file_frame) |x| allocator.free(x) else |_| {}
687 };
688
689 download_awaited = true;
690 const download_text = try await download_frame;
691 defer allocator.free(download_text);
692
693 file_awaited = true;
694 const file_text = try await file_frame;
695 defer allocator.free(file_text);
696
697 try expect(std.mem.eql(u8, "expected download text", download_text));
698 try expect(std.mem.eql(u8, "expected file text", file_text));
699 }
700
701 var global_download_frame: anyframe = undefined;
702 fn fetchUrl(allocator: *std.mem.Allocator, url: []const u8) anyerror![]u8 {
703 const result = try std.mem.dupe(allocator, u8, "expected download text");
704 errdefer allocator.free(result);
705 if (suspend_download) {
706 suspend {
707 global_download_frame = @frame();
708 }
709 }
710 if (simulate_fail_download) return error.NoResponse;
711 return result;
712 }
713
714 var global_file_frame: anyframe = undefined;
715 fn readFile(allocator: *std.mem.Allocator, filename: []const u8) anyerror![]u8 {
716 const result = try std.mem.dupe(allocator, u8, "expected file text");
717 errdefer allocator.free(result);
718 if (suspend_file) {
719 suspend {
720 global_file_frame = @frame();
721 }
722 }
723 if (simulate_fail_file) return error.FileNotFound;
724 return result;
725 }
726 };
727}
728
729test "alignment of local variables in async functions" {
730 const S = struct {
731 fn doTheTest() !void {
732 var y: u8 = 123;
733 var x: u8 align(128) = 1;
734 try expect(@ptrToInt(&x) % 128 == 0);
735 }
736 };
737 try S.doTheTest();
738}
739
740test "no reason to resolve frame still works" {
741 _ = async simpleNothing();
742}
743fn simpleNothing() void {
744 var x: i32 = 1234;
745}
746
747test "async call a generic function" {
748 const S = struct {
749 fn doTheTest() !void {
750 var f = async func(i32, 2);
751 const result = await f;
752 try expect(result == 3);
753 }
754
755 fn func(comptime T: type, inc: T) T {
756 var x: T = 1;
757 suspend {
758 resume @frame();
759 }
760 x += inc;
761 return x;
762 }
763 };
764 _ = async S.doTheTest();
765}
766
767test "return from suspend block" {
768 const S = struct {
769 fn doTheTest() !void {
770 expect(func() == 1234) catch @panic("test failure");
771 }
772 fn func() i32 {
773 suspend {
774 return 1234;
775 }
776 }
777 };
778 _ = async S.doTheTest();
779}
780
781test "struct parameter to async function is copied to the frame" {
782 const S = struct {
783 const Point = struct {
784 x: i32,
785 y: i32,
786 };
787
788 var frame: anyframe = undefined;
789
790 fn doTheTest() void {
791 _ = async atest();
792 resume frame;
793 }
794
795 fn atest() void {
796 var f: @Frame(foo) = undefined;
797 bar(&f);
798 clobberStack(10);
799 }
800
801 fn clobberStack(x: i32) void {
802 if (x == 0) return;
803 clobberStack(x - 1);
804 var y: i32 = x;
805 }
806
807 fn bar(f: *@Frame(foo)) void {
808 var pt = Point{ .x = 1, .y = 2 };
809 f.* = async foo(pt);
810 var result = await f;
811 expect(result == 1) catch @panic("test failure");
812 }
813
814 fn foo(point: Point) i32 {
815 suspend {
816 frame = @frame();
817 }
818 return point.x;
819 }
820 };
821 S.doTheTest();
822}
823
824test "cast fn to async fn when it is inferred to be async" {
825 const S = struct {
826 var frame: anyframe = undefined;
827 var ok = false;
828
829 fn doTheTest() void {
830 var ptr: fn () callconv(.Async) i32 = undefined;
831 ptr = func;
832 var buf: [100]u8 align(16) = undefined;
833 var result: i32 = undefined;
834 const f = @asyncCall(&buf, &result, ptr, .{});
835 _ = await f;
836 expect(result == 1234) catch @panic("test failure");
837 ok = true;
838 }
839
840 fn func() i32 {
841 suspend {
842 frame = @frame();
843 }
844 return 1234;
845 }
846 };
847 _ = async S.doTheTest();
848 resume S.frame;
849 try expect(S.ok);
850}
851
852test "cast fn to async fn when it is inferred to be async, awaited directly" {
853 const S = struct {
854 var frame: anyframe = undefined;
855 var ok = false;
856
857 fn doTheTest() void {
858 var ptr: fn () callconv(.Async) i32 = undefined;
859 ptr = func;
860 var buf: [100]u8 align(16) = undefined;
861 var result: i32 = undefined;
862 _ = await @asyncCall(&buf, &result, ptr, .{});
863 expect(result == 1234) catch @panic("test failure");
864 ok = true;
865 }
866
867 fn func() i32 {
868 suspend {
869 frame = @frame();
870 }
871 return 1234;
872 }
873 };
874 _ = async S.doTheTest();
875 resume S.frame;
876 try expect(S.ok);
877}
878
879test "await does not force async if callee is blocking" {
880 const S = struct {
881 fn simple() i32 {
882 return 1234;
883 }
884 };
885 var x = async S.simple();
886 try expect(await x == 1234);
887}
888
889test "recursive async function" {
890 try expect(recursiveAsyncFunctionTest(false).doTheTest() == 55);
891 try expect(recursiveAsyncFunctionTest(true).doTheTest() == 55);
892}
893
894fn recursiveAsyncFunctionTest(comptime suspending_implementation: bool) type {
895 return struct {
896 fn fib(allocator: *std.mem.Allocator, x: u32) error{OutOfMemory}!u32 {
897 if (x <= 1) return x;
898
899 if (suspending_implementation) {
900 suspend {
901 resume @frame();
902 }
903 }
904
905 const f1 = try allocator.create(@Frame(fib));
906 defer allocator.destroy(f1);
907
908 const f2 = try allocator.create(@Frame(fib));
909 defer allocator.destroy(f2);
910
911 f1.* = async fib(allocator, x - 1);
912 var f1_awaited = false;
913 errdefer if (!f1_awaited) {
914 _ = await f1;
915 };
916
917 f2.* = async fib(allocator, x - 2);
918 var f2_awaited = false;
919 errdefer if (!f2_awaited) {
920 _ = await f2;
921 };
922
923 var sum: u32 = 0;
924
925 f1_awaited = true;
926 sum += try await f1;
927
928 f2_awaited = true;
929 sum += try await f2;
930
931 return sum;
932 }
933
934 fn doTheTest() u32 {
935 if (suspending_implementation) {
936 var result: u32 = undefined;
937 _ = async amain(&result);
938 return result;
939 } else {
940 return fib(std.testing.allocator, 10) catch unreachable;
941 }
942 }
943
944 fn amain(result: *u32) void {
945 var x = async fib(std.testing.allocator, 10);
946 result.* = (await x) catch unreachable;
947 }
948 };
949}
950
951test "@asyncCall with comptime-known function, but not awaited directly" {
952 const S = struct {
953 var global_frame: anyframe = undefined;
954
955 fn doTheTest() !void {
956 var frame: [1]@Frame(middle) = undefined;
957 var result: @typeInfo(@typeInfo(@TypeOf(middle)).Fn.return_type.?).ErrorUnion.error_set!void = undefined;
958 _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle, .{});
959 resume global_frame;
960 try std.testing.expectError(error.Fail, result);
961 }
962 fn middle() callconv(.Async) !void {
963 var f = async middle2();
964 return await f;
965 }
966
967 fn middle2() !void {
968 return failing();
969 }
970
971 fn failing() !void {
972 global_frame = @frame();
973 suspend {}
974 return error.Fail;
975 }
976 };
977 try S.doTheTest();
978}
979
980test "@asyncCall with actual frame instead of byte buffer" {
981 const S = struct {
982 fn func() i32 {
983 suspend {}
984 return 1234;
985 }
986 };
987 var frame: @Frame(S.func) = undefined;
988 var result: i32 = undefined;
989 const ptr = @asyncCall(&frame, &result, S.func, .{});
990 resume ptr;
991 try expect(result == 1234);
992}
993
994test "@asyncCall using the result location inside the frame" {
995 const S = struct {
996 fn simple2(y: *i32) callconv(.Async) i32 {
997 defer y.* += 2;
998 y.* += 1;
999 suspend {}
1000 return 1234;
1001 }
1002 fn getAnswer(f: anyframe->i32, out: *i32) void {
1003 out.* = await f;
1004 }
1005 };
1006 var data: i32 = 1;
1007 const Foo = struct {
1008 bar: fn (*i32) callconv(.Async) i32,
1009 };
1010 var foo = Foo{ .bar = S.simple2 };
1011 var bytes: [64]u8 align(16) = undefined;
1012 const f = @asyncCall(&bytes, {}, foo.bar, .{&data});
1013 comptime try expect(@TypeOf(f) == anyframe->i32);
1014 try expect(data == 2);
1015 resume f;
1016 try expect(data == 4);
1017 _ = async S.getAnswer(f, &data);
1018 try expect(data == 1234);
1019}
1020
1021test "@TypeOf an async function call of generic fn with error union type" {
1022 const S = struct {
1023 fn func(comptime x: anytype) anyerror!i32 {
1024 const T = @TypeOf(async func(x));
1025 comptime try expect(T == @typeInfo(@TypeOf(@frame())).Pointer.child);
1026 return undefined;
1027 }
1028 };
1029 _ = async S.func(i32);
1030}
1031
1032test "using @TypeOf on a generic function call" {
1033 const S = struct {
1034 var global_frame: anyframe = undefined;
1035 var global_ok = false;
1036
1037 var buf: [100]u8 align(16) = undefined;
1038
1039 fn amain(x: anytype) void {
1040 if (x == 0) {
1041 global_ok = true;
1042 return;
1043 }
1044 suspend {
1045 global_frame = @frame();
1046 }
1047 const F = @TypeOf(async amain(x - 1));
1048 const frame = @intToPtr(*F, @ptrToInt(&buf));
1049 return await @asyncCall(frame, {}, amain, .{x - 1});
1050 }
1051 };
1052 _ = async S.amain(@as(u32, 1));
1053 resume S.global_frame;
1054 try expect(S.global_ok);
1055}
1056
1057test "recursive call of await @asyncCall with struct return type" {
1058 const S = struct {
1059 var global_frame: anyframe = undefined;
1060 var global_ok = false;
1061
1062 var buf: [100]u8 align(16) = undefined;
1063
1064 fn amain(x: anytype) Foo {
1065 if (x == 0) {
1066 global_ok = true;
1067 return Foo{ .x = 1, .y = 2, .z = 3 };
1068 }
1069 suspend {
1070 global_frame = @frame();
1071 }
1072 const F = @TypeOf(async amain(x - 1));
1073 const frame = @intToPtr(*F, @ptrToInt(&buf));
1074 return await @asyncCall(frame, {}, amain, .{x - 1});
1075 }
1076
1077 const Foo = struct {
1078 x: u64,
1079 y: u64,
1080 z: u64,
1081 };
1082 };
1083 var res: S.Foo = undefined;
1084 var frame: @TypeOf(async S.amain(@as(u32, 1))) = undefined;
1085 _ = @asyncCall(&frame, &res, S.amain, .{@as(u32, 1)});
1086 resume S.global_frame;
1087 try expect(S.global_ok);
1088 try expect(res.x == 1);
1089 try expect(res.y == 2);
1090 try expect(res.z == 3);
1091}
1092
1093test "nosuspend function call" {
1094 const S = struct {
1095 fn doTheTest() !void {
1096 const result = nosuspend add(50, 100);
1097 try expect(result == 150);
1098 }
1099 fn add(a: i32, b: i32) i32 {
1100 if (a > 100) {
1101 suspend {}
1102 }
1103 return a + b;
1104 }
1105 };
1106 try S.doTheTest();
1107}
1108
1109test "await used in expression and awaiting fn with no suspend but async calling convention" {
1110 const S = struct {
1111 fn atest() void {
1112 var f1 = async add(1, 2);
1113 var f2 = async add(3, 4);
1114
1115 const sum = (await f1) + (await f2);
1116 expect(sum == 10) catch @panic("test failure");
1117 }
1118 fn add(a: i32, b: i32) callconv(.Async) i32 {
1119 return a + b;
1120 }
1121 };
1122 _ = async S.atest();
1123}
1124
1125test "await used in expression after a fn call" {
1126 const S = struct {
1127 fn atest() void {
1128 var f1 = async add(3, 4);
1129 var sum: i32 = 0;
1130 sum = foo() + await f1;
1131 expect(sum == 8) catch @panic("test failure");
1132 }
1133 fn add(a: i32, b: i32) callconv(.Async) i32 {
1134 return a + b;
1135 }
1136 fn foo() i32 {
1137 return 1;
1138 }
1139 };
1140 _ = async S.atest();
1141}
1142
1143test "async fn call used in expression after a fn call" {
1144 const S = struct {
1145 fn atest() void {
1146 var sum: i32 = 0;
1147 sum = foo() + add(3, 4);
1148 expect(sum == 8) catch @panic("test failure");
1149 }
1150 fn add(a: i32, b: i32) callconv(.Async) i32 {
1151 return a + b;
1152 }
1153 fn foo() i32 {
1154 return 1;
1155 }
1156 };
1157 _ = async S.atest();
1158}
1159
1160test "suspend in for loop" {
1161 const S = struct {
1162 var global_frame: ?anyframe = null;
1163
1164 fn doTheTest() void {
1165 _ = async atest();
1166 while (global_frame) |f| resume f;
1167 }
1168
1169 fn atest() void {
1170 expect(func(&[_]u8{ 1, 2, 3 }) == 6) catch @panic("test failure");
1171 }
1172 fn func(stuff: []const u8) u32 {
1173 global_frame = @frame();
1174 var sum: u32 = 0;
1175 for (stuff) |x| {
1176 suspend {}
1177 sum += x;
1178 }
1179 global_frame = null;
1180 return sum;
1181 }
1182 };
1183 S.doTheTest();
1184}
1185
1186test "suspend in while loop" {
1187 const S = struct {
1188 var global_frame: ?anyframe = null;
1189
1190 fn doTheTest() void {
1191 _ = async atest();
1192 while (global_frame) |f| resume f;
1193 }
1194
1195 fn atest() void {
1196 expect(optional(6) == 6) catch @panic("test failure");
1197 expect(errunion(6) == 6) catch @panic("test failure");
1198 }
1199 fn optional(stuff: ?u32) u32 {
1200 global_frame = @frame();
1201 defer global_frame = null;
1202 while (stuff) |val| {
1203 suspend {}
1204 return val;
1205 }
1206 return 0;
1207 }
1208 fn errunion(stuff: anyerror!u32) u32 {
1209 global_frame = @frame();
1210 defer global_frame = null;
1211 while (stuff) |val| {
1212 suspend {}
1213 return val;
1214 } else |err| {
1215 return 0;
1216 }
1217 }
1218 };
1219 S.doTheTest();
1220}
1221
1222test "correctly spill when returning the error union result of another async fn" {
1223 const S = struct {
1224 var global_frame: anyframe = undefined;
1225
1226 fn doTheTest() !void {
1227 expect((atest() catch unreachable) == 1234) catch @panic("test failure");
1228 }
1229
1230 fn atest() !i32 {
1231 return fallible1();
1232 }
1233
1234 fn fallible1() anyerror!i32 {
1235 suspend {
1236 global_frame = @frame();
1237 }
1238 return 1234;
1239 }
1240 };
1241 _ = async S.doTheTest();
1242 resume S.global_frame;
1243}
1244
1245test "spill target expr in a for loop" {
1246 const S = struct {
1247 var global_frame: anyframe = undefined;
1248
1249 fn doTheTest() !void {
1250 var foo = Foo{
1251 .slice = &[_]i32{ 1, 2 },
1252 };
1253 expect(atest(&foo) == 3) catch @panic("test failure");
1254 }
1255
1256 const Foo = struct {
1257 slice: []const i32,
1258 };
1259
1260 fn atest(foo: *Foo) i32 {
1261 var sum: i32 = 0;
1262 for (foo.slice) |x| {
1263 suspend {
1264 global_frame = @frame();
1265 }
1266 sum += x;
1267 }
1268 return sum;
1269 }
1270 };
1271 _ = async S.doTheTest();
1272 resume S.global_frame;
1273 resume S.global_frame;
1274}
1275
1276test "spill target expr in a for loop, with a var decl in the loop body" {
1277 const S = struct {
1278 var global_frame: anyframe = undefined;
1279
1280 fn doTheTest() !void {
1281 var foo = Foo{
1282 .slice = &[_]i32{ 1, 2 },
1283 };
1284 expect(atest(&foo) == 3) catch @panic("test failure");
1285 }
1286
1287 const Foo = struct {
1288 slice: []const i32,
1289 };
1290
1291 fn atest(foo: *Foo) i32 {
1292 var sum: i32 = 0;
1293 for (foo.slice) |x| {
1294 // Previously this var decl would prevent spills. This test makes sure
1295 // the for loop spills still happen even though there is a VarDecl in scope
1296 // before the suspend.
1297 var anything = true;
1298 _ = anything;
1299 suspend {
1300 global_frame = @frame();
1301 }
1302 sum += x;
1303 }
1304 return sum;
1305 }
1306 };
1307 _ = async S.doTheTest();
1308 resume S.global_frame;
1309 resume S.global_frame;
1310}
1311
1312test "async call with @call" {
1313 const S = struct {
1314 var global_frame: anyframe = undefined;
1315 fn doTheTest() void {
1316 _ = @call(.{ .modifier = .async_kw }, atest, .{});
1317 resume global_frame;
1318 }
1319 fn atest() void {
1320 var frame = @call(.{ .modifier = .async_kw }, afoo, .{});
1321 const res = await frame;
1322 expect(res == 42) catch @panic("test failure");
1323 }
1324 fn afoo() i32 {
1325 suspend {
1326 global_frame = @frame();
1327 }
1328 return 42;
1329 }
1330 };
1331 S.doTheTest();
1332}
1333
1334test "async function passed 0-bit arg after non-0-bit arg" {
1335 const S = struct {
1336 var global_frame: anyframe = undefined;
1337 var global_int: i32 = 0;
1338
1339 fn foo() void {
1340 bar(1, .{}) catch unreachable;
1341 }
1342
1343 fn bar(x: i32, args: anytype) anyerror!void {
1344 global_frame = @frame();
1345 suspend {}
1346 global_int = x;
1347 }
1348 };
1349 _ = async S.foo();
1350 resume S.global_frame;
1351 try expect(S.global_int == 1);
1352}
1353
1354test "async function passed align(16) arg after align(8) arg" {
1355 const S = struct {
1356 var global_frame: anyframe = undefined;
1357 var global_int: u128 = 0;
1358
1359 fn foo() void {
1360 var a: u128 = 99;
1361 bar(10, .{a}) catch unreachable;
1362 }
1363
1364 fn bar(x: u64, args: anytype) anyerror!void {
1365 try expect(x == 10);
1366 global_frame = @frame();
1367 suspend {}
1368 global_int = args[0];
1369 }
1370 };
1371 _ = async S.foo();
1372 resume S.global_frame;
1373 try expect(S.global_int == 99);
1374}
1375
1376test "async function call resolves target fn frame, comptime func" {
1377 const S = struct {
1378 var global_frame: anyframe = undefined;
1379 var global_int: i32 = 9;
1380
1381 fn foo() anyerror!void {
1382 const stack_size = 1000;
1383 var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
1384 return await @asyncCall(&stack_frame, {}, bar, .{});
1385 }
1386
1387 fn bar() anyerror!void {
1388 global_frame = @frame();
1389 suspend {}
1390 global_int += 1;
1391 }
1392 };
1393 _ = async S.foo();
1394 resume S.global_frame;
1395 try expect(S.global_int == 10);
1396}
1397
1398test "async function call resolves target fn frame, runtime func" {
1399 const S = struct {
1400 var global_frame: anyframe = undefined;
1401 var global_int: i32 = 9;
1402
1403 fn foo() anyerror!void {
1404 const stack_size = 1000;
1405 var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
1406 var func: fn () callconv(.Async) anyerror!void = bar;
1407 return await @asyncCall(&stack_frame, {}, func, .{});
1408 }
1409
1410 fn bar() anyerror!void {
1411 global_frame = @frame();
1412 suspend {}
1413 global_int += 1;
1414 }
1415 };
1416 _ = async S.foo();
1417 resume S.global_frame;
1418 try expect(S.global_int == 10);
1419}
1420
1421test "properly spill optional payload capture value" {
1422 const S = struct {
1423 var global_frame: anyframe = undefined;
1424 var global_int: usize = 2;
1425
1426 fn foo() void {
1427 var opt: ?usize = 1234;
1428 if (opt) |x| {
1429 bar();
1430 global_int += x;
1431 }
1432 }
1433
1434 fn bar() void {
1435 global_frame = @frame();
1436 suspend {}
1437 global_int += 1;
1438 }
1439 };
1440 _ = async S.foo();
1441 resume S.global_frame;
1442 try expect(S.global_int == 1237);
1443}
1444
1445test "handle defer interfering with return value spill" {
1446 const S = struct {
1447 var global_frame1: anyframe = undefined;
1448 var global_frame2: anyframe = undefined;
1449 var finished = false;
1450 var baz_happened = false;
1451
1452 fn doTheTest() !void {
1453 _ = async testFoo();
1454 resume global_frame1;
1455 resume global_frame2;
1456 try expect(baz_happened);
1457 try expect(finished);
1458 }
1459
1460 fn testFoo() void {
1461 expectError(error.Bad, foo()) catch @panic("test failure");
1462 finished = true;
1463 }
1464
1465 fn foo() anyerror!void {
1466 defer baz();
1467 return bar() catch |err| return err;
1468 }
1469
1470 fn bar() anyerror!void {
1471 global_frame1 = @frame();
1472 suspend {}
1473 return error.Bad;
1474 }
1475
1476 fn baz() void {
1477 global_frame2 = @frame();
1478 suspend {}
1479 baz_happened = true;
1480 }
1481 };
1482 try S.doTheTest();
1483}
1484
1485test "take address of temporary async frame" {
1486 const S = struct {
1487 var global_frame: anyframe = undefined;
1488 var finished = false;
1489
1490 fn doTheTest() !void {
1491 _ = async asyncDoTheTest();
1492 resume global_frame;
1493 try expect(finished);
1494 }
1495
1496 fn asyncDoTheTest() void {
1497 expect(finishIt(&async foo(10)) == 1245) catch @panic("test failure");
1498 finished = true;
1499 }
1500
1501 fn foo(arg: i32) i32 {
1502 global_frame = @frame();
1503 suspend {}
1504 return arg + 1234;
1505 }
1506
1507 fn finishIt(frame: anyframe->i32) i32 {
1508 return (await frame) + 1;
1509 }
1510 };
1511 try S.doTheTest();
1512}
1513
1514test "nosuspend await" {
1515 const S = struct {
1516 var finished = false;
1517
1518 fn doTheTest() !void {
1519 var frame = async foo(false);
1520 try expect(nosuspend await frame == 42);
1521 finished = true;
1522 }
1523
1524 fn foo(want_suspend: bool) i32 {
1525 if (want_suspend) {
1526 suspend {}
1527 }
1528 return 42;
1529 }
1530 };
1531 try S.doTheTest();
1532 try expect(S.finished);
1533}
1534
1535test "nosuspend on function calls" {
1536 const S0 = struct {
1537 b: i32 = 42,
1538 };
1539 const S1 = struct {
1540 fn c() S0 {
1541 return S0{};
1542 }
1543 fn d() !S0 {
1544 return S0{};
1545 }
1546 };
1547 try expectEqual(@as(i32, 42), nosuspend S1.c().b);
1548 try expectEqual(@as(i32, 42), (try nosuspend S1.d()).b);
1549}
1550
1551test "nosuspend on async function calls" {
1552 const S0 = struct {
1553 b: i32 = 42,
1554 };
1555 const S1 = struct {
1556 fn c() S0 {
1557 return S0{};
1558 }
1559 fn d() !S0 {
1560 return S0{};
1561 }
1562 };
1563 var frame_c = nosuspend async S1.c();
1564 try expectEqual(@as(i32, 42), (await frame_c).b);
1565 var frame_d = nosuspend async S1.d();
1566 try expectEqual(@as(i32, 42), (try await frame_d).b);
1567}
1568
1569// test "resume nosuspend async function calls" {
1570// const S0 = struct {
1571// b: i32 = 42,
1572// };
1573// const S1 = struct {
1574// fn c() S0 {
1575// suspend {}
1576// return S0{};
1577// }
1578// fn d() !S0 {
1579// suspend {}
1580// return S0{};
1581// }
1582// };
1583// var frame_c = nosuspend async S1.c();
1584// resume frame_c;
1585// try expectEqual(@as(i32, 42), (await frame_c).b);
1586// var frame_d = nosuspend async S1.d();
1587// resume frame_d;
1588// try expectEqual(@as(i32, 42), (try await frame_d).b);
1589// }
1590
1591test "nosuspend resume async function calls" {
1592 const S0 = struct {
1593 b: i32 = 42,
1594 };
1595 const S1 = struct {
1596 fn c() S0 {
1597 suspend {}
1598 return S0{};
1599 }
1600 fn d() !S0 {
1601 suspend {}
1602 return S0{};
1603 }
1604 };
1605 var frame_c = async S1.c();
1606 nosuspend resume frame_c;
1607 try expectEqual(@as(i32, 42), (await frame_c).b);
1608 var frame_d = async S1.d();
1609 nosuspend resume frame_d;
1610 try expectEqual(@as(i32, 42), (try await frame_d).b);
1611}
1612
1613test "avoid forcing frame alignment resolution implicit cast to *c_void" {
1614 const S = struct {
1615 var x: ?*c_void = null;
1616
1617 fn foo() bool {
1618 suspend {
1619 x = @frame();
1620 }
1621 return true;
1622 }
1623 };
1624 var frame = async S.foo();
1625 resume @ptrCast(anyframe->bool, @alignCast(@alignOf(@Frame(S.foo)), S.x));
1626 try expect(nosuspend await frame);
1627}
1628
1629test "@asyncCall with pass-by-value arguments" {
1630 const F0: u64 = 0xbeefbeefbeefbeef;
1631 const F1: u64 = 0xf00df00df00df00d;
1632 const F2: u64 = 0xcafecafecafecafe;
1633
1634 const S = struct {
1635 pub const ST = struct { f0: usize, f1: usize };
1636 pub const AT = [5]u8;
1637
1638 pub fn f(_fill0: u64, s: ST, _fill1: u64, a: AT, _fill2: u64) callconv(.Async) void {
1639 // Check that the array and struct arguments passed by value don't
1640 // end up overflowing the adjacent fields in the frame structure.
1641 expectEqual(F0, _fill0) catch @panic("test failure");
1642 expectEqual(F1, _fill1) catch @panic("test failure");
1643 expectEqual(F2, _fill2) catch @panic("test failure");
1644 }
1645 };
1646
1647 var buffer: [1024]u8 align(@alignOf(@Frame(S.f))) = undefined;
1648 // The function pointer must not be comptime-known.
1649 var t = S.f;
1650 var frame_ptr = @asyncCall(&buffer, {}, t, .{
1651 F0,
1652 .{ .f0 = 1, .f1 = 2 },
1653 F1,
1654 [_]u8{ 1, 2, 3, 4, 5 },
1655 F2,
1656 });
1657}
1658
1659test "@asyncCall with arguments having non-standard alignment" {
1660 const F0: u64 = 0xbeefbeef;
1661 const F1: u64 = 0xf00df00df00df00d;
1662
1663 const S = struct {
1664 pub fn f(_fill0: u32, s: struct { x: u64 align(16) }, _fill1: u64) callconv(.Async) void {
1665 // The compiler inserts extra alignment for s, check that the
1666 // generated code picks the right slot for fill1.
1667 expectEqual(F0, _fill0) catch @panic("test failure");
1668 expectEqual(F1, _fill1) catch @panic("test failure");
1669 }
1670 };
1671
1672 var buffer: [1024]u8 align(@alignOf(@Frame(S.f))) = undefined;
1673 // The function pointer must not be comptime-known.
1674 var t = S.f;
1675 var frame_ptr = @asyncCall(&buffer, {}, t, .{ F0, undefined, F1 });
1676}
test/stage1/behavior/atomics.zig deleted-219
...@@ -1,219 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const builtin = @import("builtin");
5
6test "cmpxchg" {
7 try testCmpxchg();
8 comptime try testCmpxchg();
9}
10
11fn testCmpxchg() !void {
12 var x: i32 = 1234;
13 if (@cmpxchgWeak(i32, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
14 try expect(x1 == 1234);
15 } else {
16 @panic("cmpxchg should have failed");
17 }
18
19 while (@cmpxchgWeak(i32, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
20 try expect(x1 == 1234);
21 }
22 try expect(x == 5678);
23
24 try expect(@cmpxchgStrong(i32, &x, 5678, 42, .SeqCst, .SeqCst) == null);
25 try expect(x == 42);
26}
27
28test "fence" {
29 var x: i32 = 1234;
30 @fence(.SeqCst);
31 x = 5678;
32}
33
34test "atomicrmw and atomicload" {
35 var data: u8 = 200;
36 try testAtomicRmw(&data);
37 try expect(data == 42);
38 try testAtomicLoad(&data);
39}
40
41fn testAtomicRmw(ptr: *u8) !void {
42 const prev_value = @atomicRmw(u8, ptr, .Xchg, 42, .SeqCst);
43 try expect(prev_value == 200);
44 comptime {
45 var x: i32 = 1234;
46 const y: i32 = 12345;
47 try expect(@atomicLoad(i32, &x, .SeqCst) == 1234);
48 try expect(@atomicLoad(i32, &y, .SeqCst) == 12345);
49 }
50}
51
52fn testAtomicLoad(ptr: *u8) !void {
53 const x = @atomicLoad(u8, ptr, .SeqCst);
54 try expect(x == 42);
55}
56
57test "cmpxchg with ptr" {
58 var data1: i32 = 1234;
59 var data2: i32 = 5678;
60 var data3: i32 = 9101;
61 var x: *i32 = &data1;
62 if (@cmpxchgWeak(*i32, &x, &data2, &data3, .SeqCst, .SeqCst)) |x1| {
63 try expect(x1 == &data1);
64 } else {
65 @panic("cmpxchg should have failed");
66 }
67
68 while (@cmpxchgWeak(*i32, &x, &data1, &data3, .SeqCst, .SeqCst)) |x1| {
69 try expect(x1 == &data1);
70 }
71 try expect(x == &data3);
72
73 try expect(@cmpxchgStrong(*i32, &x, &data3, &data2, .SeqCst, .SeqCst) == null);
74 try expect(x == &data2);
75}
76
77// TODO this test is disabled until this issue is resolved:
78// https://github.com/ziglang/zig/issues/2883
79// otherwise cross compiling will result in:
80// lld: error: undefined symbol: __sync_val_compare_and_swap_16
81//test "128-bit cmpxchg" {
82// var x: u128 align(16) = 1234; // TODO: https://github.com/ziglang/zig/issues/2987
83// if (@cmpxchgWeak(u128, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
84// try expect(x1 == 1234);
85// } else {
86// @panic("cmpxchg should have failed");
87// }
88//
89// while (@cmpxchgWeak(u128, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
90// try expect(x1 == 1234);
91// }
92// try expect(x == 5678);
93//
94// try expect(@cmpxchgStrong(u128, &x, 5678, 42, .SeqCst, .SeqCst) == null);
95// try expect(x == 42);
96//}
97
98test "cmpxchg with ignored result" {
99 var x: i32 = 1234;
100 var ptr = &x;
101
102 _ = @cmpxchgStrong(i32, &x, 1234, 5678, .Monotonic, .Monotonic);
103
104 try expectEqual(@as(i32, 5678), x);
105}
106
107var a_global_variable = @as(u32, 1234);
108
109test "cmpxchg on a global variable" {
110 _ = @cmpxchgWeak(u32, &a_global_variable, 1234, 42, .Acquire, .Monotonic);
111 try expectEqual(@as(u32, 42), a_global_variable);
112}
113
114test "atomic load and rmw with enum" {
115 const Value = enum(u8) {
116 a,
117 b,
118 c,
119 };
120 var x = Value.a;
121
122 try expect(@atomicLoad(Value, &x, .SeqCst) != .b);
123
124 _ = @atomicRmw(Value, &x, .Xchg, .c, .SeqCst);
125 try expect(@atomicLoad(Value, &x, .SeqCst) == .c);
126 try expect(@atomicLoad(Value, &x, .SeqCst) != .a);
127 try expect(@atomicLoad(Value, &x, .SeqCst) != .b);
128}
129
130test "atomic store" {
131 var x: u32 = 0;
132 @atomicStore(u32, &x, 1, .SeqCst);
133 try expect(@atomicLoad(u32, &x, .SeqCst) == 1);
134 @atomicStore(u32, &x, 12345678, .SeqCst);
135 try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678);
136}
137
138test "atomic store comptime" {
139 comptime try testAtomicStore();
140 try testAtomicStore();
141}
142
143fn testAtomicStore() !void {
144 var x: u32 = 0;
145 @atomicStore(u32, &x, 1, .SeqCst);
146 try expect(@atomicLoad(u32, &x, .SeqCst) == 1);
147 @atomicStore(u32, &x, 12345678, .SeqCst);
148 try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678);
149}
150
151test "atomicrmw with floats" {
152 switch (builtin.arch) {
153 // https://github.com/ziglang/zig/issues/4457
154 .aarch64, .arm, .thumb, .riscv64 => return error.SkipZigTest,
155 else => {},
156 }
157 try testAtomicRmwFloat();
158 comptime try testAtomicRmwFloat();
159}
160
161fn testAtomicRmwFloat() !void {
162 var x: f32 = 0;
163 try expect(x == 0);
164 _ = @atomicRmw(f32, &x, .Xchg, 1, .SeqCst);
165 try expect(x == 1);
166 _ = @atomicRmw(f32, &x, .Add, 5, .SeqCst);
167 try expect(x == 6);
168 _ = @atomicRmw(f32, &x, .Sub, 2, .SeqCst);
169 try expect(x == 4);
170}
171
172test "atomicrmw with ints" {
173 try testAtomicRmwInt();
174 comptime try testAtomicRmwInt();
175}
176
177fn testAtomicRmwInt() !void {
178 var x: u8 = 1;
179 var res = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst);
180 try expect(x == 3 and res == 1);
181 _ = @atomicRmw(u8, &x, .Add, 3, .SeqCst);
182 try expect(x == 6);
183 _ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst);
184 try expect(x == 5);
185 _ = @atomicRmw(u8, &x, .And, 4, .SeqCst);
186 try expect(x == 4);
187 _ = @atomicRmw(u8, &x, .Nand, 4, .SeqCst);
188 try expect(x == 0xfb);
189 _ = @atomicRmw(u8, &x, .Or, 6, .SeqCst);
190 try expect(x == 0xff);
191 _ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst);
192 try expect(x == 0xfd);
193
194 _ = @atomicRmw(u8, &x, .Max, 1, .SeqCst);
195 try expect(x == 0xfd);
196 _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
197 try expect(x == 1);
198}
199
200test "atomics with different types" {
201 try testAtomicsWithType(bool, true, false);
202 inline for (.{ u1, i4, u5, i15, u24 }) |T| {
203 var x: T = 0;
204 try testAtomicsWithType(T, 0, 1);
205 }
206 try testAtomicsWithType(u0, 0, 0);
207 try testAtomicsWithType(i0, 0, 0);
208}
209
210fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {
211 var x: T = b;
212 @atomicStore(T, &x, a, .SeqCst);
213 try expect(x == a);
214 try expect(@atomicLoad(T, &x, .SeqCst) == a);
215 try expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a);
216 try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null);
217 if (@sizeOf(T) != 0)
218 try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a);
219}
test/stage1/behavior/await_struct.zig deleted-44
...@@ -1,44 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5const Foo = struct {
6 x: i32,
7};
8
9var await_a_promise: anyframe = undefined;
10var await_final_result = Foo{ .x = 0 };
11
12test "coroutine await struct" {
13 await_seq('a');
14 var p = async await_amain();
15 await_seq('f');
16 resume await_a_promise;
17 await_seq('i');
18 try expect(await_final_result.x == 1234);
19 try expect(std.mem.eql(u8, &await_points, "abcdefghi"));
20}
21fn await_amain() callconv(.Async) void {
22 await_seq('b');
23 var p = async await_another();
24 await_seq('e');
25 await_final_result = await p;
26 await_seq('h');
27}
28fn await_another() callconv(.Async) Foo {
29 await_seq('c');
30 suspend {
31 await_seq('d');
32 await_a_promise = @frame();
33 }
34 await_seq('g');
35 return Foo{ .x = 1234 };
36}
37
38var await_points = [_]u8{0} ** "abcdefghi".len;
39var await_seq_index: usize = 0;
40
41fn await_seq(c: u8) void {
42 await_points[await_seq_index] = c;
43 await_seq_index += 1;
44}
test/stage1/behavior/bit_shifting.zig deleted-104
...@@ -1,104 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
5 const key_bits = @typeInfo(Key).Int.bits;
6 std.debug.assert(Key == std.meta.Int(.unsigned, key_bits));
7 std.debug.assert(key_bits >= mask_bit_count);
8 const shard_key_bits = mask_bit_count;
9 const ShardKey = std.meta.Int(.unsigned, mask_bit_count);
10 const shift_amount = key_bits - shard_key_bits;
11 return struct {
12 const Self = @This();
13 shards: [1 << shard_key_bits]?*Node,
14
15 pub fn create() Self {
16 return Self{ .shards = [_]?*Node{null} ** (1 << shard_key_bits) };
17 }
18
19 fn getShardKey(key: Key) ShardKey {
20 // https://github.com/ziglang/zig/issues/1544
21 // this special case is needed because you can't u32 >> 32.
22 if (ShardKey == u0) return 0;
23
24 // this can be u1 >> u0
25 const shard_key = key >> shift_amount;
26
27 // TODO: https://github.com/ziglang/zig/issues/1544
28 // This cast could be implicit if we teach the compiler that
29 // u32 >> 30 -> u2
30 return @intCast(ShardKey, shard_key);
31 }
32
33 pub fn put(self: *Self, node: *Node) void {
34 const shard_key = Self.getShardKey(node.key);
35 node.next = self.shards[shard_key];
36 self.shards[shard_key] = node;
37 }
38
39 pub fn get(self: *Self, key: Key) ?*Node {
40 const shard_key = Self.getShardKey(key);
41 var maybe_node = self.shards[shard_key];
42 while (maybe_node) |node| : (maybe_node = node.next) {
43 if (node.key == key) return node;
44 }
45 return null;
46 }
47
48 pub const Node = struct {
49 key: Key,
50 value: V,
51 next: ?*Node,
52
53 pub fn init(self: *Node, key: Key, value: V) void {
54 self.key = key;
55 self.value = value;
56 self.next = null;
57 }
58 };
59 };
60}
61
62test "sharded table" {
63 // realistic 16-way sharding
64 try testShardedTable(u32, 4, 8);
65
66 try testShardedTable(u5, 0, 32); // ShardKey == u0
67 try testShardedTable(u5, 2, 32);
68 try testShardedTable(u5, 5, 32);
69
70 try testShardedTable(u1, 0, 2);
71 try testShardedTable(u1, 1, 2); // this does u1 >> u0
72
73 try testShardedTable(u0, 0, 1);
74}
75fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) !void {
76 const Table = ShardedTable(Key, mask_bit_count, void);
77
78 var table = Table.create();
79 var node_buffer: [node_count]Table.Node = undefined;
80 for (node_buffer) |*node, i| {
81 const key = @intCast(Key, i);
82 try expect(table.get(key) == null);
83 node.init(key, {});
84 table.put(node);
85 }
86
87 for (node_buffer) |*node, i| {
88 try expect(table.get(@intCast(Key, i)) == node);
89 }
90}
91
92// #2225
93test "comptime shr of BigInt" {
94 comptime {
95 var n0 = 0xdeadbeef0000000000000000;
96 try expect(n0 >> 64 == 0xdeadbeef);
97 var n1 = 17908056155735594659;
98 try expect(n1 >> 64 == 0);
99 }
100}
101
102test "comptime shift safety check" {
103 const x = @as(usize, 42) << @sizeOf(usize);
104}
test/stage1/behavior/bitcast.zig deleted-196
...@@ -1,196 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;
5const maxInt = std.math.maxInt;
6
7test "@bitCast i32 -> u32" {
8 try testBitCast_i32_u32();
9 comptime try testBitCast_i32_u32();
10}
11
12fn testBitCast_i32_u32() !void {
13 try expect(conv(-1) == maxInt(u32));
14 try expect(conv2(maxInt(u32)) == -1);
15}
16
17fn conv(x: i32) u32 {
18 return @bitCast(u32, x);
19}
20fn conv2(x: u32) i32 {
21 return @bitCast(i32, x);
22}
23
24test "@bitCast extern enum to its integer type" {
25 const SOCK = extern enum {
26 A,
27 B,
28
29 fn testBitCastExternEnum() !void {
30 var SOCK_DGRAM = @This().B;
31 var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
32 try expect(sock_dgram == 1);
33 }
34 };
35
36 try SOCK.testBitCastExternEnum();
37 comptime try SOCK.testBitCastExternEnum();
38}
39
40test "@bitCast packed structs at runtime and comptime" {
41 const Full = packed struct {
42 number: u16,
43 };
44 const Divided = packed struct {
45 half1: u8,
46 quarter3: u4,
47 quarter4: u4,
48 };
49 const S = struct {
50 fn doTheTest() !void {
51 var full = Full{ .number = 0x1234 };
52 var two_halves = @bitCast(Divided, full);
53 switch (builtin.endian) {
54 builtin.Endian.Big => {
55 try expect(two_halves.half1 == 0x12);
56 try expect(two_halves.quarter3 == 0x3);
57 try expect(two_halves.quarter4 == 0x4);
58 },
59 builtin.Endian.Little => {
60 try expect(two_halves.half1 == 0x34);
61 try expect(two_halves.quarter3 == 0x2);
62 try expect(two_halves.quarter4 == 0x1);
63 },
64 }
65 }
66 };
67 try S.doTheTest();
68 comptime try S.doTheTest();
69}
70
71test "@bitCast extern structs at runtime and comptime" {
72 const Full = extern struct {
73 number: u16,
74 };
75 const TwoHalves = extern struct {
76 half1: u8,
77 half2: u8,
78 };
79 const S = struct {
80 fn doTheTest() !void {
81 var full = Full{ .number = 0x1234 };
82 var two_halves = @bitCast(TwoHalves, full);
83 switch (builtin.endian) {
84 builtin.Endian.Big => {
85 try expect(two_halves.half1 == 0x12);
86 try expect(two_halves.half2 == 0x34);
87 },
88 builtin.Endian.Little => {
89 try expect(two_halves.half1 == 0x34);
90 try expect(two_halves.half2 == 0x12);
91 },
92 }
93 }
94 };
95 try S.doTheTest();
96 comptime try S.doTheTest();
97}
98
99test "bitcast packed struct to integer and back" {
100 const LevelUpMove = packed struct {
101 move_id: u9,
102 level: u7,
103 };
104 const S = struct {
105 fn doTheTest() !void {
106 var move = LevelUpMove{ .move_id = 1, .level = 2 };
107 var v = @bitCast(u16, move);
108 var back_to_a_move = @bitCast(LevelUpMove, v);
109 try expect(back_to_a_move.move_id == 1);
110 try expect(back_to_a_move.level == 2);
111 }
112 };
113 try S.doTheTest();
114 comptime try S.doTheTest();
115}
116
117test "implicit cast to error union by returning" {
118 const S = struct {
119 fn entry() !void {
120 try expect((func(-1) catch unreachable) == maxInt(u64));
121 }
122 pub fn func(sz: i64) anyerror!u64 {
123 return @bitCast(u64, sz);
124 }
125 };
126 try S.entry();
127 comptime try S.entry();
128}
129
130// issue #3010: compiler segfault
131test "bitcast literal [4]u8 param to u32" {
132 const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
133 try expect(ip == maxInt(u32));
134}
135
136test "bitcast packed struct literal to byte" {
137 const Foo = packed struct {
138 value: u8,
139 };
140 const casted = @bitCast(u8, Foo{ .value = 0xF });
141 try expect(casted == 0xf);
142}
143
144test "comptime bitcast used in expression has the correct type" {
145 const Foo = packed struct {
146 value: u8,
147 };
148 try expect(@bitCast(u8, Foo{ .value = 0xF }) == 0xf);
149}
150
151test "bitcast result to _" {
152 _ = @bitCast(u8, @as(i8, 1));
153}
154
155test "nested bitcast" {
156 const S = struct {
157 fn moo(x: isize) !void {
158 try @import("std").testing.expectEqual(@intCast(isize, 42), x);
159 }
160
161 fn foo(x: isize) !void {
162 try @This().moo(
163 @bitCast(isize, if (x != 0) @bitCast(usize, x) else @bitCast(usize, x)),
164 );
165 }
166 };
167
168 try S.foo(42);
169 comptime try S.foo(42);
170}
171
172test "bitcast passed as tuple element" {
173 const S = struct {
174 fn foo(args: anytype) !void {
175 comptime try expect(@TypeOf(args[0]) == f32);
176 try expect(args[0] == 12.34);
177 }
178 };
179 try S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))});
180}
181
182test "triple level result location with bitcast sandwich passed as tuple element" {
183 const S = struct {
184 fn foo(args: anytype) !void {
185 comptime try expect(@TypeOf(args[0]) == f64);
186 try expect(args[0] > 12.33 and args[0] < 12.35);
187 }
188 };
189 try S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
190}
191
192test "bitcast generates a temporary value" {
193 var y = @as(u16, 0x55AA);
194 const x = @bitCast(u16, @bitCast([2]u8, y));
195 try expectEqual(y, x);
196}
test/stage1/behavior/bitreverse.zig deleted-69
...@@ -1,69 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const minInt = std.math.minInt;
4
5test "@bitReverse" {
6 comptime try testBitReverse();
7 try testBitReverse();
8}
9
10fn testBitReverse() !void {
11 // using comptime_ints, unsigned
12 try expect(@bitReverse(u0, 0) == 0);
13 try expect(@bitReverse(u5, 0x12) == 0x9);
14 try expect(@bitReverse(u8, 0x12) == 0x48);
15 try expect(@bitReverse(u16, 0x1234) == 0x2c48);
16 try expect(@bitReverse(u24, 0x123456) == 0x6a2c48);
17 try expect(@bitReverse(u32, 0x12345678) == 0x1e6a2c48);
18 try expect(@bitReverse(u40, 0x123456789a) == 0x591e6a2c48);
19 try expect(@bitReverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
20 try expect(@bitReverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
21 try expect(@bitReverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
22 try expect(@bitReverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
23
24 // using runtime uints, unsigned
25 var num0: u0 = 0;
26 try expect(@bitReverse(u0, num0) == 0);
27 var num5: u5 = 0x12;
28 try expect(@bitReverse(u5, num5) == 0x9);
29 var num8: u8 = 0x12;
30 try expect(@bitReverse(u8, num8) == 0x48);
31 var num16: u16 = 0x1234;
32 try expect(@bitReverse(u16, num16) == 0x2c48);
33 var num24: u24 = 0x123456;
34 try expect(@bitReverse(u24, num24) == 0x6a2c48);
35 var num32: u32 = 0x12345678;
36 try expect(@bitReverse(u32, num32) == 0x1e6a2c48);
37 var num40: u40 = 0x123456789a;
38 try expect(@bitReverse(u40, num40) == 0x591e6a2c48);
39 var num48: u48 = 0x123456789abc;
40 try expect(@bitReverse(u48, num48) == 0x3d591e6a2c48);
41 var num56: u56 = 0x123456789abcde;
42 try expect(@bitReverse(u56, num56) == 0x7b3d591e6a2c48);
43 var num64: u64 = 0x123456789abcdef1;
44 try expect(@bitReverse(u64, num64) == 0x8f7b3d591e6a2c48);
45 var num128: u128 = 0x123456789abcdef11121314151617181;
46 try expect(@bitReverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
47
48 // using comptime_ints, signed, positive
49 try expect(@bitReverse(u8, @as(u8, 0)) == 0);
50 try expect(@bitReverse(i8, @bitCast(i8, @as(u8, 0x92))) == @bitCast(i8, @as(u8, 0x49)));
51 try expect(@bitReverse(i16, @bitCast(i16, @as(u16, 0x1234))) == @bitCast(i16, @as(u16, 0x2c48)));
52 try expect(@bitReverse(i24, @bitCast(i24, @as(u24, 0x123456))) == @bitCast(i24, @as(u24, 0x6a2c48)));
53 try expect(@bitReverse(i32, @bitCast(i32, @as(u32, 0x12345678))) == @bitCast(i32, @as(u32, 0x1e6a2c48)));
54 try expect(@bitReverse(i40, @bitCast(i40, @as(u40, 0x123456789a))) == @bitCast(i40, @as(u40, 0x591e6a2c48)));
55 try expect(@bitReverse(i48, @bitCast(i48, @as(u48, 0x123456789abc))) == @bitCast(i48, @as(u48, 0x3d591e6a2c48)));
56 try expect(@bitReverse(i56, @bitCast(i56, @as(u56, 0x123456789abcde))) == @bitCast(i56, @as(u56, 0x7b3d591e6a2c48)));
57 try expect(@bitReverse(i64, @bitCast(i64, @as(u64, 0x123456789abcdef1))) == @bitCast(i64, @as(u64, 0x8f7b3d591e6a2c48)));
58 try expect(@bitReverse(i128, @bitCast(i128, @as(u128, 0x123456789abcdef11121314151617181))) == @bitCast(i128, @as(u128, 0x818e868a828c84888f7b3d591e6a2c48)));
59
60 // using signed, negative. Compare to runtime ints returned from llvm.
61 var neg8: i8 = -18;
62 try expect(@bitReverse(i8, @as(i8, -18)) == @bitReverse(i8, neg8));
63 var neg16: i16 = -32694;
64 try expect(@bitReverse(i16, @as(i16, -32694)) == @bitReverse(i16, neg16));
65 var neg24: i24 = -6773785;
66 try expect(@bitReverse(i24, @as(i24, -6773785)) == @bitReverse(i24, neg24));
67 var neg32: i32 = -16773785;
68 try expect(@bitReverse(i32, @as(i32, -16773785)) == @bitReverse(i32, neg32));
69}
test/stage1/behavior/bool.zig deleted-35
...@@ -1,35 +0,0 @@
1const expect = @import("std").testing.expect;
2
3test "bool literals" {
4 try expect(true);
5 try expect(!false);
6}
7
8test "cast bool to int" {
9 const t = true;
10 const f = false;
11 try expect(@boolToInt(t) == @as(u32, 1));
12 try expect(@boolToInt(f) == @as(u32, 0));
13 try nonConstCastBoolToInt(t, f);
14}
15
16fn nonConstCastBoolToInt(t: bool, f: bool) !void {
17 try expect(@boolToInt(t) == @as(u32, 1));
18 try expect(@boolToInt(f) == @as(u32, 0));
19}
20
21test "bool cmp" {
22 try expect(testBoolCmp(true, false) == false);
23}
24fn testBoolCmp(a: bool, b: bool) bool {
25 return a == b;
26}
27
28const global_f = false;
29const global_t = true;
30const not_global_f = !global_f;
31const not_global_t = !global_t;
32test "compile time bool not" {
33 try expect(not_global_f);
34 try expect(!not_global_t);
35}
test/stage1/behavior/bugs/1025.zig deleted-12
...@@ -1,12 +0,0 @@
1const A = struct {
2 B: type,
3};
4
5fn getA() A {
6 return A{ .B = u8 };
7}
8
9test "bug 1025" {
10 const a = getA();
11 try @import("std").testing.expect(a.B == u8);
12}
test/stage1/behavior/bugs/1076.zig deleted-23
...@@ -1,23 +0,0 @@
1const std = @import("std");
2const mem = std.mem;
3const expect = std.testing.expect;
4
5test "comptime code should not modify constant data" {
6 try testCastPtrOfArrayToSliceAndPtr();
7 comptime try testCastPtrOfArrayToSliceAndPtr();
8}
9
10fn testCastPtrOfArrayToSliceAndPtr() !void {
11 {
12 var array = "aoeu".*;
13 const x: [*]u8 = &array;
14 x[0] += 1;
15 try expect(mem.eql(u8, array[0..], "boeu"));
16 }
17 {
18 var array: [4]u8 = "aoeu".*;
19 const x: [*]u8 = &array;
20 x[0] += 1;
21 try expect(mem.eql(u8, array[0..], "boeu"));
22 }
23}
test/stage1/behavior/bugs/1111.zig deleted-11
...@@ -1,11 +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 }
11}
test/stage1/behavior/bugs/1120.zig deleted-23
...@@ -1,23 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const A = packed struct {
5 a: u2,
6 b: u6,
7};
8const B = packed struct {
9 q: u8,
10 a: u2,
11 b: u6,
12};
13test "bug 1120" {
14 var a = A{ .a = 2, .b = 2 };
15 var b = B{ .q = 22, .a = 3, .b = 2 };
16 var t: usize = 0;
17 const ptr = switch (t) {
18 0 => &a.a,
19 1 => &b.a,
20 else => unreachable,
21 };
22 try expect(ptr.* == 2);
23}
test/stage1/behavior/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 try std.testing.expect(s.f.?() == 1234);
15}
test/stage1/behavior/bugs/1310.zig deleted-24
...@@ -1,24 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4pub const VM = ?[*]const struct_InvocationTable_;
5pub const struct_InvocationTable_ = extern struct {
6 GetVM: ?fn (?[*]VM) callconv(.C) c_int,
7};
8
9pub const struct_VM_ = extern struct {
10 functions: ?[*]const struct_InvocationTable_,
11};
12
13//excised output from stdlib.h etc
14
15pub const InvocationTable_ = struct_InvocationTable_;
16pub const VM_ = struct_VM_;
17
18fn agent_callback(_vm: [*]VM, options: [*]u8) callconv(.C) i32 {
19 return 11;
20}
21
22test "fixed" {
23 try expect(agent_callback(undefined, undefined) == 11);
24}
test/stage1/behavior/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 try std.testing.expect(@as(std.meta.Tag(B), a.b) == std.meta.Tag(B).c);
17 a = A{ .b = B.None };
18 try std.testing.expect(@as(std.meta.Tag(B), a.b) == std.meta.Tag(B).None);
19}
test/stage1/behavior/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 try std.testing.expect(a.D == 1);
21}
test/stage1/behavior/bugs/1421.zig deleted-14
...@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5const S = struct {
6 fn method() builtin.TypeInfo {
7 return @typeInfo(S);
8 }
9};
10
11test "functions with return type required to be comptime are generic" {
12 const ti = S.method();
13 try expect(@as(builtin.TypeId, ti) == builtin.TypeId.Struct);
14}
test/stage1/behavior/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 try std.testing.expect((union_or_err catch unreachable).Color == 1234);
11}
test/stage1/behavior/bugs/1467.zig deleted-7
...@@ -1,7 +0,0 @@
1pub const E = enum(u32) { A, B, C };
2pub const S = extern struct {
3 e: E,
4};
5test "bug 1467" {
6 const s: S = undefined;
7}
test/stage1/behavior/bugs/1486.zig deleted-10
...@@ -1,10 +0,0 @@
1const expect = @import("std").testing.expect;
2
3const ptr = &global;
4var global: u64 = 123;
5
6test "constant pointer to global variable causes runtime load" {
7 global = 1234;
8 try expect(&global == ptr);
9 try expect(ptr.* == 1234);
10}
test/stage1/behavior/bugs/1500.zig deleted-10
...@@ -1,10 +0,0 @@
1const A = struct {
2 b: B,
3};
4
5const B = fn (A) void;
6
7test "allow these dependencies" {
8 var a: A = undefined;
9 var b: B = undefined;
10}
test/stage1/behavior/bugs/1607.zig deleted-15
...@@ -1,15 +0,0 @@
1const std = @import("std");
2const testing = std.testing;
3
4const a = [_]u8{ 1, 2, 3 };
5
6fn checkAddress(s: []const u8) !void {
7 for (s) |*i, j| {
8 try testing.expect(i == &a[j]);
9 }
10}
11
12test "slices pointing at the same address as global array." {
13 try checkAddress(&a);
14 comptime try checkAddress(&a);
15}
test/stage1/behavior/bugs/1735.zig deleted-46
...@@ -1,46 +0,0 @@
1const std = @import("std");
2
3const mystruct = struct {
4 pending: ?listofstructs,
5};
6pub fn TailQueue(comptime T: type) type {
7 return struct {
8 const Self = @This();
9
10 pub const Node = struct {
11 prev: ?*Node,
12 next: ?*Node,
13 data: T,
14 };
15
16 first: ?*Node,
17 last: ?*Node,
18 len: usize,
19
20 pub fn init() Self {
21 return Self{
22 .first = null,
23 .last = null,
24 .len = 0,
25 };
26 }
27 };
28}
29const listofstructs = TailQueue(mystruct);
30
31const a = struct {
32 const Self = @This();
33
34 foo: listofstructs,
35
36 pub fn init() Self {
37 return Self{
38 .foo = listofstructs.init(),
39 };
40 }
41};
42
43test "intialization" {
44 var t = a.init();
45 try std.testing.expect(t.foo.len == 0);
46}
test/stage1/behavior/bugs/1741.zig deleted-6
...@@ -1,6 +0,0 @@
1const std = @import("std");
2
3test "fixed" {
4 const x: f32 align(128) = 12.34;
5 try std.testing.expect(@ptrToInt(&x) % 128 == 0);
6}
test/stage1/behavior/bugs/1851.zig deleted-26
...@@ -1,26 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "allocation and looping over 3-byte integer" {
5 try expect(@sizeOf(u24) == 4);
6 try expect(@sizeOf([1]u24) == 4);
7 try expect(@alignOf(u24) == 4);
8 try expect(@alignOf([1]u24) == 4);
9
10 var x = try std.testing.allocator.alloc(u24, 2);
11 defer std.testing.allocator.free(x);
12 try expect(x.len == 2);
13 x[0] = 0xFFFFFF;
14 x[1] = 0xFFFFFF;
15
16 const bytes = std.mem.sliceAsBytes(x);
17 try expect(@TypeOf(bytes) == []align(4) u8);
18 try expect(bytes.len == 8);
19
20 for (bytes) |*b| {
21 b.* = 0x00;
22 }
23
24 try expect(x[0] == 0x00);
25 try expect(x[1] == 0x00);
26}
test/stage1/behavior/bugs/1914.zig deleted-31
...@@ -1,31 +0,0 @@
1const std = @import("std");
2
3const A = struct {
4 b_list_pointer: *const []B,
5};
6const B = struct {
7 a_pointer: *const A,
8};
9
10const b_list: []B = &[_]B{};
11const a = A{ .b_list_pointer = &b_list };
12
13test "segfault bug" {
14 const assert = std.debug.assert;
15 const obj = B{ .a_pointer = &a };
16 assert(obj.a_pointer == &a); // this makes zig crash
17}
18
19const A2 = struct {
20 pointer: *B,
21};
22
23pub const B2 = struct {
24 pointer_array: []*A2,
25};
26
27var b_value = B2{ .pointer_array = &[_]*A2{} };
28
29test "basic stuff" {
30 std.debug.assert(&b_value == &b_value);
31}
test/stage1/behavior/bugs/2006.zig deleted-12
...@@ -1,12 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const S = struct {
5 p: *S,
6};
7test "bug 2006" {
8 var a: S = undefined;
9 a = S{ .p = undefined };
10 try expect(@sizeOf(S) != 0);
11 try expect(@sizeOf(*void) == 0);
12}
test/stage1/behavior/bugs/2114.zig deleted-19
...@@ -1,19 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const math = std.math;
4
5fn ctz(x: anytype) usize {
6 return @ctz(@TypeOf(x), x);
7}
8
9test "fixed" {
10 try testClz();
11 comptime try testClz();
12}
13
14fn testClz() !void {
15 try expect(ctz(@as(u128, 0x40000000000000000000000000000000)) == 126);
16 try expect(math.rotl(u128, @as(u128, 0x40000000000000000000000000000000), @as(u8, 1)) == @as(u128, 0x80000000000000000000000000000000));
17 try expect(ctz(@as(u128, 0x80000000000000000000000000000000)) == 127);
18 try expect(ctz(math.rotl(u128, @as(u128, 0x40000000000000000000000000000000), @as(u8, 1))) == 127);
19}
test/stage1/behavior/bugs/2346.zig deleted-6
...@@ -1,6 +0,0 @@
1test "fixed" {
2 const a: *void = undefined;
3 const b: *[1]void = a;
4 const c: *[0]u8 = undefined;
5 const d: []u8 = c;
6}
test/stage1/behavior/bugs/2578.zig deleted-12
...@@ -1,12 +0,0 @@
1const Foo = struct {
2 y: u8,
3};
4
5var foo: Foo = undefined;
6const t = &foo;
7
8fn bar(pointer: ?*c_void) void {}
9
10test "fixed" {
11 bar(t);
12}
test/stage1/behavior/bugs/2692.zig deleted-6
...@@ -1,6 +0,0 @@
1fn foo(a: []u8) void {}
2
3test "address of 0 length array" {
4 var pt: [0]u8 = undefined;
5 foo(&pt);
6}
test/stage1/behavior/bugs/2889.zig deleted-31
...@@ -1,31 +0,0 @@
1const std = @import("std");
2
3const source = "A-";
4
5fn parseNote() ?i32 {
6 const letter = source[0];
7 const modifier = source[1];
8
9 const semitone = blk: {
10 if (letter == 'C' and modifier == '-') break :blk @as(i32, 0);
11 if (letter == 'C' and modifier == '#') break :blk @as(i32, 1);
12 if (letter == 'D' and modifier == '-') break :blk @as(i32, 2);
13 if (letter == 'D' and modifier == '#') break :blk @as(i32, 3);
14 if (letter == 'E' and modifier == '-') break :blk @as(i32, 4);
15 if (letter == 'F' and modifier == '-') break :blk @as(i32, 5);
16 if (letter == 'F' and modifier == '#') break :blk @as(i32, 6);
17 if (letter == 'G' and modifier == '-') break :blk @as(i32, 7);
18 if (letter == 'G' and modifier == '#') break :blk @as(i32, 8);
19 if (letter == 'A' and modifier == '-') break :blk @as(i32, 9);
20 if (letter == 'A' and modifier == '#') break :blk @as(i32, 10);
21 if (letter == 'B' and modifier == '-') break :blk @as(i32, 11);
22 return null;
23 };
24
25 return semitone;
26}
27
28test "fixed" {
29 const result = parseNote();
30 try std.testing.expect(result.? == 9);
31}
test/stage1/behavior/bugs/3007.zig deleted-23
...@@ -1,23 +0,0 @@
1const std = @import("std");
2
3const Foo = struct {
4 free: bool,
5
6 pub const FooError = error{NotFree};
7};
8
9var foo = Foo{ .free = true };
10var default_foo: ?*Foo = null;
11
12fn get_foo() Foo.FooError!*Foo {
13 if (foo.free) {
14 foo.free = false;
15 return &foo;
16 }
17 return error.NotFree;
18}
19
20test "fixed" {
21 default_foo = get_foo() catch null; // This Line
22 try std.testing.expect(!default_foo.?.free);
23}
test/stage1/behavior/bugs/3046.zig deleted-19
...@@ -1,19 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const SomeStruct = struct {
5 field: i32,
6};
7
8fn couldFail() anyerror!i32 {
9 return 1;
10}
11
12var some_struct: SomeStruct = undefined;
13
14test "fixed" {
15 some_struct = SomeStruct{
16 .field = couldFail() catch |_| @as(i32, 0),
17 };
18 try expect(some_struct.field == 1);
19}
test/stage1/behavior/bugs/3112.zig deleted-17
...@@ -1,17 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const State = struct {
5 const Self = @This();
6 enter: fn (previous: ?Self) void,
7};
8
9fn prev(p: ?State) void {
10 expect(p == null) catch @panic("test failure");
11}
12
13test "zig test crash" {
14 var global: State = undefined;
15 global.enter = prev;
16 global.enter(null);
17}
test/stage1/behavior/bugs/3367.zig deleted-12
...@@ -1,12 +0,0 @@
1const Foo = struct {
2 usingnamespace Mixin;
3};
4
5const Mixin = struct {
6 pub fn two(self: Foo) void {}
7};
8
9test "container member access usingnamespace decls" {
10 var foo = Foo{};
11 foo.two();
12}
test/stage1/behavior/bugs/3384.zig deleted-11
...@@ -1,11 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "resolve array slice using builtin" {
5 try expect(@hasDecl(@This(), "std") == true);
6 try expect(@hasDecl(@This(), "std"[0..0]) == false);
7 try expect(@hasDecl(@This(), "std"[0..1]) == false);
8 try expect(@hasDecl(@This(), "std"[0..2]) == false);
9 try expect(@hasDecl(@This(), "std"[0..3]) == true);
10 try expect(@hasDecl(@This(), "std"[0..]) == true);
11}
test/stage1/behavior/bugs/3468.zig deleted-6
...@@ -1,6 +0,0 @@
1// zig fmt: off
2test "pointer deref next to assignment" {
3 var a:i32=2;
4 var b=&a;
5 b.*=3;
6}
test/stage1/behavior/bugs/3586.zig deleted-11
...@@ -1,11 +0,0 @@
1const NoteParams = struct {};
2
3const Container = struct {
4 params: ?NoteParams,
5};
6
7test "fixed" {
8 var ctr = Container{
9 .params = NoteParams{},
10 };
11}
test/stage1/behavior/bugs/3742.zig deleted-38
...@@ -1,38 +0,0 @@
1const std = @import("std");
2
3pub const GET = struct {
4 key: []const u8,
5
6 pub fn init(key: []const u8) GET {
7 return .{ .key = key };
8 }
9
10 pub const Redis = struct {
11 pub const Command = struct {
12 pub fn serialize(self: GET, comptime rootSerializer: type) void {
13 return rootSerializer.serializeCommand(.{ "GET", self.key });
14 }
15 };
16 };
17};
18
19pub fn isCommand(comptime T: type) bool {
20 const tid = @typeInfo(T);
21 return (tid == .Struct or tid == .Enum or tid == .Union) and
22 @hasDecl(T, "Redis") and @hasDecl(T.Redis, "Command");
23}
24
25pub const ArgSerializer = struct {
26 pub fn serializeCommand(command: anytype) void {
27 const CmdT = @TypeOf(command);
28
29 if (comptime isCommand(CmdT)) {
30 // COMMENTING THE NEXT LINE REMOVES THE ERROR
31 return CmdT.Redis.Command.serialize(command, ArgSerializer);
32 }
33 }
34};
35
36test "fixed" {
37 ArgSerializer.serializeCommand(GET.init("banana"));
38}
test/stage1/behavior/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 expect = @import("std").testing.expect;
11
12test "bug 394 fixed" {
13 const x = S{
14 .x = 3,
15 .y = E{ .B = 1 },
16 };
17 try expect(x.x == 3);
18}
test/stage1/behavior/bugs/421.zig deleted-15
...@@ -1,15 +0,0 @@
1const expect = @import("std").testing.expect;
2
3test "bitCast to array" {
4 comptime try testBitCastArray();
5 try testBitCastArray();
6}
7
8fn testBitCastArray() !void {
9 try expect(extractOne64(0x0123456789abcdef0123456789abcdef) == 0x0123456789abcdef);
10}
11
12fn extractOne64(a: u128) u64 {
13 const x = @bitCast([2]u64, a);
14 return x[1];
15}
test/stage1/behavior/bugs/4328.zig deleted-71
...@@ -1,71 +0,0 @@
1const expectEqual = @import("std").testing.expectEqual;
2
3const FILE = extern struct {
4 dummy_field: u8,
5};
6
7extern fn printf([*c]const u8, ...) c_int;
8extern fn fputs([*c]const u8, noalias [*c]FILE) c_int;
9extern fn ftell([*c]FILE) c_long;
10extern fn fopen([*c]const u8, [*c]const u8) [*c]FILE;
11
12const S = extern struct {
13 state: c_short,
14
15 extern fn s_do_thing([*c]S, b: c_int) c_short;
16};
17
18test "Extern function calls in @TypeOf" {
19 const Test = struct {
20 fn test_fn_1(a: anytype, b: anytype) @TypeOf(printf("%d %s\n", a, b)) {
21 return 0;
22 }
23
24 fn test_fn_2(a: anytype) @TypeOf((S{ .state = 0 }).s_do_thing(a)) {
25 return 1;
26 }
27
28 fn doTheTest() !void {
29 try expectEqual(c_int, @TypeOf(test_fn_1(0, 42)));
30 try expectEqual(c_short, @TypeOf(test_fn_2(0)));
31 }
32 };
33
34 try Test.doTheTest();
35 comptime try Test.doTheTest();
36}
37
38test "Peer resolution of extern function calls in @TypeOf" {
39 const Test = struct {
40 fn test_fn() @TypeOf(ftell(null), fputs(null, null)) {
41 return 0;
42 }
43
44 fn doTheTest() !void {
45 try expectEqual(c_long, @TypeOf(test_fn()));
46 }
47 };
48
49 try Test.doTheTest();
50 comptime try Test.doTheTest();
51}
52
53test "Extern function calls, dereferences and field access in @TypeOf" {
54 const Test = struct {
55 fn test_fn_1(a: c_long) @TypeOf(fopen("test", "r").*) {
56 return .{ .dummy_field = 0 };
57 }
58
59 fn test_fn_2(a: anytype) @TypeOf(fopen("test", "r").*.dummy_field) {
60 return 255;
61 }
62
63 fn doTheTest() !void {
64 try expectEqual(FILE, @TypeOf(test_fn_1(0)));
65 try expectEqual(u8, @TypeOf(test_fn_2(0)));
66 }
67 };
68
69 try Test.doTheTest();
70 comptime try Test.doTheTest();
71}
test/stage1/behavior/bugs/4560.zig deleted-32
...@@ -1,32 +0,0 @@
1const std = @import("std");
2
3test "fixed" {
4 var s: S = .{
5 .a = 1,
6 .b = .{
7 .size = 123,
8 .max_distance_from_start_index = 456,
9 },
10 };
11 try std.testing.expect(s.a == 1);
12 try std.testing.expect(s.b.size == 123);
13 try std.testing.expect(s.b.max_distance_from_start_index == 456);
14}
15
16const S = struct {
17 a: u32,
18 b: Map,
19
20 const Map = StringHashMap(*S);
21};
22
23pub fn StringHashMap(comptime V: type) type {
24 return HashMap([]const u8, V);
25}
26
27pub fn HashMap(comptime K: type, comptime V: type) type {
28 return struct {
29 size: usize,
30 max_distance_from_start_index: usize,
31 };
32}
test/stage1/behavior/bugs/4769_a.zig deleted-1
...@@ -1 +0,0 @@
1//
test/stage1/behavior/bugs/4769_b.zig deleted-1
...@@ -1 +0,0 @@
1//!
test/stage1/behavior/bugs/4769_c.zig deleted-1
...@@ -1 +0,0 @@
1///
\ No newline at end of file
test/stage1/behavior/bugs/4954.zig deleted-8
...@@ -1,8 +0,0 @@
1fn f(buf: []u8) void {
2 var ptr = &buf[@sizeOf(u32)];
3}
4
5test "crash" {
6 var buf: [4096]u8 = undefined;
7 f(&buf);
8}
test/stage1/behavior/bugs/529.zig deleted-14
...@@ -1,14 +0,0 @@
1const A = extern struct {
2 field: c_int,
3};
4
5extern fn issue529(?*A) void;
6
7comptime {
8 _ = @import("529_other_file_2.zig");
9}
10
11test "issue 529 fixed" {
12 @import("529_other_file.zig").issue529(null);
13 issue529(null);
14}
test/stage1/behavior/bugs/529_other_file.zig deleted-5
...@@ -1,5 +0,0 @@
1pub const A = extern struct {
2 field: c_int,
3};
4
5pub extern fn issue529(?*A) void;
test/stage1/behavior/bugs/529_other_file_2.zig deleted-4
...@@ -1,4 +0,0 @@
1pub const A = extern struct {
2 field: c_int,
3};
4export fn issue529(a: ?*A) void {}
test/stage1/behavior/bugs/5398.zig deleted-31
...@@ -1,31 +0,0 @@
1const std = @import("std");
2const testing = std.testing;
3
4pub const Mesh = struct {
5 id: u32,
6};
7pub const Material = struct {
8 transparent: bool = true,
9 emits_shadows: bool = true,
10 render_color: bool = true,
11};
12pub const Renderable = struct {
13 material: Material,
14 // The compiler inserts some padding here to ensure Mesh is correctly aligned.
15 mesh: Mesh,
16};
17
18var renderable: Renderable = undefined;
19
20test "assignment of field with padding" {
21 renderable = Renderable{
22 .mesh = Mesh{ .id = 0 },
23 .material = Material{
24 .transparent = false,
25 .emits_shadows = false,
26 },
27 };
28 try testing.expectEqual(false, renderable.material.transparent);
29 try testing.expectEqual(false, renderable.material.emits_shadows);
30 try testing.expectEqual(true, renderable.material.render_color);
31}
test/stage1/behavior/bugs/5413.zig deleted-6
...@@ -1,6 +0,0 @@
1const expect = @import("std").testing.expect;
2
3test "Peer type resolution with string literals and unknown length u8 pointers" {
4 try expect(@TypeOf("", "a", @as([*:0]const u8, "")) == [*:0]const u8);
5 try expect(@TypeOf(@as([*:0]const u8, "baz"), "foo", "bar") == [*:0]const u8);
6}
test/stage1/behavior/bugs/5474.zig deleted-57
...@@ -1,57 +0,0 @@
1const std = @import("std");
2
3// baseline (control) struct with array of scalar
4const Box0 = struct {
5 items: [4]Item,
6
7 const Item = struct {
8 num: u32,
9 };
10};
11
12// struct with array of empty struct
13const Box1 = struct {
14 items: [4]Item,
15
16 const Item = struct {};
17};
18
19// struct with array of zero-size struct
20const Box2 = struct {
21 items: [4]Item,
22
23 const Item = struct {
24 nothing: void,
25 };
26};
27
28fn doTest() !void {
29 // var
30 {
31 var box0: Box0 = .{ .items = undefined };
32 try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == false);
33
34 var box1: Box1 = .{ .items = undefined };
35 try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == false);
36
37 var box2: Box2 = .{ .items = undefined };
38 try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == false);
39 }
40
41 // const
42 {
43 const box0: Box0 = .{ .items = undefined };
44 try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == true);
45
46 const box1: Box1 = .{ .items = undefined };
47 try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == true);
48
49 const box2: Box2 = .{ .items = undefined };
50 try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == true);
51 }
52}
53
54test "pointer-to-array constness for zero-size elements" {
55 try doTest();
56 comptime try doTest();
57}
test/stage1/behavior/bugs/5487.zig deleted-12
...@@ -1,12 +0,0 @@
1const io = @import("std").io;
2
3pub fn write(_: void, bytes: []const u8) !usize {
4 return 0;
5}
6pub fn writer() io.Writer(void, @typeInfo(@typeInfo(@TypeOf(write)).Fn.return_type.?).ErrorUnion.error_set, write) {
7 return io.Writer(void, @typeInfo(@typeInfo(@TypeOf(write)).Fn.return_type.?).ErrorUnion.error_set, write){ .context = {} };
8}
9
10test "crash" {
11 _ = io.multiWriter(.{writer()});
12}
test/stage1/behavior/bugs/624.zig deleted-23
...@@ -1,23 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const TestContext = struct {
5 server_context: *ListenerContext,
6};
7
8const ListenerContext = struct {
9 context_alloc: *ContextAllocator,
10};
11
12const ContextAllocator = MemoryPool(TestContext);
13
14fn MemoryPool(comptime T: type) type {
15 return struct {
16 n: usize,
17 };
18}
19
20test "foo" {
21 var allocator = ContextAllocator{ .n = 10 };
22 try expect(allocator.n == 10);
23}
test/stage1/behavior/bugs/6456.zig deleted-43
...@@ -1,43 +0,0 @@
1const std = @import("std");
2const testing = std.testing;
3const builtin = @import("builtin");
4const StructField = builtin.TypeInfo.StructField;
5const Declaration = builtin.TypeInfo.Declaration;
6
7const text =
8 \\f1
9 \\f2
10 \\f3
11;
12
13test "issue 6456" {
14 comptime {
15 var fields: []const StructField = &[0]StructField{};
16
17 var it = std.mem.tokenize(text, "\n");
18 while (it.next()) |name| {
19 fields = fields ++ &[_]StructField{StructField{
20 .alignment = 0,
21 .name = name,
22 .field_type = usize,
23 .default_value = @as(?usize, null),
24 .is_comptime = false,
25 }};
26 }
27
28 const T = @Type(.{
29 .Struct = .{
30 .layout = .Auto,
31 .is_tuple = false,
32 .fields = fields,
33 .decls = &[_]Declaration{},
34 },
35 });
36
37 const gen_fields = @typeInfo(T).Struct.fields;
38 try testing.expectEqual(3, gen_fields.len);
39 try testing.expectEqualStrings("f1", gen_fields[0].name);
40 try testing.expectEqualStrings("f2", gen_fields[1].name);
41 try testing.expectEqualStrings("f3", gen_fields[2].name);
42 }
43}
test/stage1/behavior/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 try std.testing.expect(@TypeOf(&x) == *const other_file.Integer);
7 try foo(&x);
8}
9
10fn foo(x: *const other_file.Integer) !void {
11 try std.testing.expect(x.* == 1234);
12}
test/stage1/behavior/bugs/655_other_file.zig deleted-1
...@@ -1 +0,0 @@
1pub const Integer = u32;
test/stage1/behavior/bugs/656.zig deleted-31
...@@ -1,31 +0,0 @@
1const expect = @import("std").testing.expect;
2
3const PrefixOp = union(enum) {
4 Return,
5 AddrOf: Value,
6};
7
8const Value = struct {
9 align_expr: ?u32,
10};
11
12test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {
13 try 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 try expect(align_expr == 1234);
26 }
27 },
28 PrefixOp.Return => {},
29 }
30 }
31}
test/stage1/behavior/bugs/6781.zig deleted-74
...@@ -1,74 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4const segfault = true;
5
6pub const JournalHeader = packed struct {
7 hash_chain_root: u128 = undefined,
8 prev_hash_chain_root: u128,
9 checksum: u128 = undefined,
10 magic: u64,
11 command: u32,
12 size: u32,
13
14 pub fn calculate_checksum(self: *const JournalHeader, entry: []const u8) u128 {
15 assert(entry.len >= @sizeOf(JournalHeader));
16 assert(entry.len == self.size);
17
18 const checksum_offset = @byteOffsetOf(JournalHeader, "checksum");
19 const checksum_size = @sizeOf(@TypeOf(self.checksum));
20 assert(checksum_offset == 0 + 16 + 16);
21 assert(checksum_size == 16);
22
23 var target: [32]u8 = undefined;
24 std.crypto.hash.Blake3.hash(entry[checksum_offset + checksum_size ..], target[0..], .{});
25 return @bitCast(u128, target[0..checksum_size].*);
26 }
27
28 pub fn calculate_hash_chain_root(self: *const JournalHeader) u128 {
29 const hash_chain_root_size = @sizeOf(@TypeOf(self.hash_chain_root));
30 assert(hash_chain_root_size == 16);
31
32 const prev_hash_chain_root_offset = @byteOffsetOf(JournalHeader, "prev_hash_chain_root");
33 const prev_hash_chain_root_size = @sizeOf(@TypeOf(self.prev_hash_chain_root));
34 assert(prev_hash_chain_root_offset == 0 + 16);
35 assert(prev_hash_chain_root_size == 16);
36
37 const checksum_offset = @byteOffsetOf(JournalHeader, "checksum");
38 const checksum_size = @sizeOf(@TypeOf(self.checksum));
39 assert(checksum_offset == 0 + 16 + 16);
40 assert(checksum_size == 16);
41
42 assert(prev_hash_chain_root_offset + prev_hash_chain_root_size == checksum_offset);
43
44 const header = @bitCast([@sizeOf(JournalHeader)]u8, self.*);
45 const source = header[prev_hash_chain_root_offset .. checksum_offset + checksum_size];
46 assert(source.len == prev_hash_chain_root_size + checksum_size);
47 var target: [32]u8 = undefined;
48 std.crypto.hash.Blake3.hash(source, target[0..], .{});
49 if (segfault) {
50 return @bitCast(u128, target[0..hash_chain_root_size].*);
51 } else {
52 var array = target[0..hash_chain_root_size].*;
53 return @bitCast(u128, array);
54 }
55 }
56
57 pub fn set_checksum_and_hash_chain_root(self: *JournalHeader, entry: []const u8) void {
58 self.checksum = self.calculate_checksum(entry);
59 self.hash_chain_root = self.calculate_hash_chain_root();
60 }
61};
62
63test "fixed" {
64 var buffer = [_]u8{0} ** 65536;
65 var entry = std.mem.bytesAsValue(JournalHeader, buffer[0..@sizeOf(JournalHeader)]);
66 entry.* = .{
67 .prev_hash_chain_root = 0,
68 .magic = 0,
69 .command = 0,
70 .size = 64 + 128,
71 };
72 entry.set_checksum_and_hash_chain_root(buffer[0..entry.size]);
73 try std.io.null_writer.print("{}\n", .{entry});
74}
test/stage1/behavior/bugs/679.zig deleted-17
...@@ -1,17 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4pub fn List(comptime T: type) type {
5 return u32;
6}
7
8const ElementList = List(Element);
9const Element = struct {
10 link: ElementList,
11};
12
13test "false dependency loop in struct definition" {
14 const listType = ElementList;
15 var x: listType = 42;
16 try expect(x == 42);
17}
test/stage1/behavior/bugs/6850.zig deleted-12
...@@ -1,12 +0,0 @@
1const std = @import("std");
2
3test "lazy sizeof comparison with zero" {
4 const Empty = struct {};
5 const T = *Empty;
6
7 try std.testing.expect(hasNoBits(T));
8}
9
10fn hasNoBits(comptime T: type) bool {
11 return @sizeOf(T) == 0;
12}
test/stage1/behavior/bugs/7003.zig deleted-8
...@@ -1,8 +0,0 @@
1test "@Type should resolve its children types" {
2 const sparse = enum(u2) { a, b, c };
3 const dense = enum(u2) { a, b, c, d };
4
5 comptime var sparse_info = @typeInfo(anyerror!sparse);
6 sparse_info.ErrorUnion.payload = dense;
7 const B = @Type(sparse_info);
8}
test/stage1/behavior/bugs/7027.zig deleted-17
...@@ -1,17 +0,0 @@
1const Foobar = struct {
2 myTypes: [128]type,
3 str: [1024]u8,
4
5 fn foo() @This() {
6 comptime var foobar: Foobar = undefined;
7 foobar.str = [_]u8{'a'} ** 1024;
8 return foobar;
9 }
10};
11
12fn foo(arg: anytype) void {}
13
14test "" {
15 comptime var foobar = Foobar.foo();
16 foo(foobar.str[0..10]);
17}
test/stage1/behavior/bugs/704.zig deleted-7
...@@ -1,7 +0,0 @@
1const xxx = struct {
2 pub fn bar(self: *xxx) void {}
3};
4test "bug 704" {
5 var x: xxx = undefined;
6 x.bar();
7}
test/stage1/behavior/bugs/7047.zig deleted-22
...@@ -1,22 +0,0 @@
1const std = @import("std");
2
3const U = union(enum) {
4 T: type,
5 N: void,
6};
7
8fn S(comptime query: U) type {
9 return struct {
10 fn tag() type {
11 return query.T;
12 }
13 };
14}
15
16test "compiler doesn't consider equal unions with different 'type' payload" {
17 const s1 = S(U{ .T = u32 }).tag();
18 try std.testing.expectEqual(u32, s1);
19
20 const s2 = S(U{ .T = u64 }).tag();
21 try std.testing.expectEqual(u64, s2);
22}
test/stage1/behavior/bugs/718.zig deleted-17
...@@ -1,17 +0,0 @@
1const std = @import("std");
2const mem = std.mem;
3const expect = std.testing.expect;
4const Keys = struct {
5 up: bool,
6 down: bool,
7 left: bool,
8 right: bool,
9};
10var keys: Keys = undefined;
11test "zero keys with @memset" {
12 @memset(@ptrCast([*]u8, &keys), 0, @sizeOf(@TypeOf(keys)));
13 try expect(!keys.up);
14 try expect(!keys.down);
15 try expect(!keys.left);
16 try expect(!keys.right);
17}
test/stage1/behavior/bugs/7250.zig deleted-15
...@@ -1,15 +0,0 @@
1const nrfx_uart_t = extern struct {
2 p_reg: [*c]u32,
3 drv_inst_idx: u8,
4};
5
6pub fn nrfx_uart_rx(p_instance: [*c]const nrfx_uart_t) void {}
7
8threadlocal var g_uart0 = nrfx_uart_t{
9 .p_reg = 0,
10 .drv_inst_idx = 0,
11};
12
13test "reference a global threadlocal variable" {
14 _ = nrfx_uart_rx(&g_uart0);
15}
test/stage1/behavior/bugs/726.zig deleted-15
...@@ -1,15 +0,0 @@
1const expect = @import("std").testing.expect;
2
3test "@ptrCast from const to nullable" {
4 const c: u8 = 4;
5 var x: ?*const u8 = @ptrCast(?*const u8, &c);
6 try expect(x.?.* == 4);
7}
8
9test "@ptrCast from var in empty struct to nullable" {
10 const container = struct {
11 var c: u8 = 4;
12 };
13 var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
14 try expect(x.?.* == 4);
15}
test/stage1/behavior/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/stage1/behavior/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 try std.testing.expectEqual(NormalDist1.f[i], NormalDist.f[i]);
64 }
65}
test/stage1/behavior/byteswap.zig deleted-68
...@@ -1,68 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "@byteSwap integers" {
5 const ByteSwapIntTest = struct {
6 fn run() !void {
7 try t(u0, 0, 0);
8 try t(u8, 0x12, 0x12);
9 try t(u16, 0x1234, 0x3412);
10 try t(u24, 0x123456, 0x563412);
11 try t(u32, 0x12345678, 0x78563412);
12 try t(u40, 0x123456789a, 0x9a78563412);
13 try t(i48, 0x123456789abc, @bitCast(i48, @as(u48, 0xbc9a78563412)));
14 try t(u56, 0x123456789abcde, 0xdebc9a78563412);
15 try t(u64, 0x123456789abcdef1, 0xf1debc9a78563412);
16 try t(u128, 0x123456789abcdef11121314151617181, 0x8171615141312111f1debc9a78563412);
17
18 try t(u0, @as(u0, 0), 0);
19 try t(i8, @as(i8, -50), -50);
20 try t(i16, @bitCast(i16, @as(u16, 0x1234)), @bitCast(i16, @as(u16, 0x3412)));
21 try t(i24, @bitCast(i24, @as(u24, 0x123456)), @bitCast(i24, @as(u24, 0x563412)));
22 try t(i32, @bitCast(i32, @as(u32, 0x12345678)), @bitCast(i32, @as(u32, 0x78563412)));
23 try t(u40, @bitCast(i40, @as(u40, 0x123456789a)), @as(u40, 0x9a78563412));
24 try t(i48, @bitCast(i48, @as(u48, 0x123456789abc)), @bitCast(i48, @as(u48, 0xbc9a78563412)));
25 try t(i56, @bitCast(i56, @as(u56, 0x123456789abcde)), @bitCast(i56, @as(u56, 0xdebc9a78563412)));
26 try t(i64, @bitCast(i64, @as(u64, 0x123456789abcdef1)), @bitCast(i64, @as(u64, 0xf1debc9a78563412)));
27 try t(
28 i128,
29 @bitCast(i128, @as(u128, 0x123456789abcdef11121314151617181)),
30 @bitCast(i128, @as(u128, 0x8171615141312111f1debc9a78563412)),
31 );
32 }
33 fn t(comptime I: type, input: I, expected_output: I) !void {
34 try std.testing.expectEqual(expected_output, @byteSwap(I, input));
35 }
36 };
37 comptime try ByteSwapIntTest.run();
38 try ByteSwapIntTest.run();
39}
40
41test "@byteSwap vectors" {
42 // https://github.com/ziglang/zig/issues/3563
43 if (std.Target.current.os.tag == .dragonfly) return error.SkipZigTest;
44
45 // https://github.com/ziglang/zig/issues/3317
46 if (std.Target.current.cpu.arch == .mipsel or std.Target.current.cpu.arch == .mips) return error.SkipZigTest;
47
48 const ByteSwapVectorTest = struct {
49 fn run() !void {
50 try t(u8, 2, [_]u8{ 0x12, 0x13 }, [_]u8{ 0x12, 0x13 });
51 try t(u16, 2, [_]u16{ 0x1234, 0x2345 }, [_]u16{ 0x3412, 0x4523 });
52 try t(u24, 2, [_]u24{ 0x123456, 0x234567 }, [_]u24{ 0x563412, 0x674523 });
53 }
54
55 fn t(
56 comptime I: type,
57 comptime n: comptime_int,
58 input: std.meta.Vector(n, I),
59 expected_vector: std.meta.Vector(n, I),
60 ) !void {
61 const actual_output: [n]I = @byteSwap(I, input);
62 const expected_output: [n]I = expected_vector;
63 try std.testing.expectEqual(expected_output, actual_output);
64 }
65 };
66 comptime try ByteSwapVectorTest.run();
67 try ByteSwapVectorTest.run();
68}
test/stage1/behavior/byval_arg_var.zig deleted-27
...@@ -1,27 +0,0 @@
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 try std.testing.expect(std.mem.eql(u8, result, "string literal"));
10}
11
12fn start() void {
13 foo("string literal");
14}
15
16fn foo(x: anytype) void {
17 bar(x);
18}
19
20fn bar(x: anytype) void {
21 result = x;
22}
23
24fn blowUpStack(x: u32) void {
25 if (x == 0) return;
26 blowUpStack(x - 1);
27}
test/stage1/behavior/call.zig deleted-74
...@@ -1,74 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4
5test "basic invocations" {
6 const foo = struct {
7 fn foo() i32 {
8 return 1234;
9 }
10 }.foo;
11 try expect(@call(.{}, foo, .{}) == 1234);
12 comptime {
13 // modifiers that allow comptime calls
14 try expect(@call(.{}, foo, .{}) == 1234);
15 try expect(@call(.{ .modifier = .no_async }, foo, .{}) == 1234);
16 try expect(@call(.{ .modifier = .always_tail }, foo, .{}) == 1234);
17 try expect(@call(.{ .modifier = .always_inline }, foo, .{}) == 1234);
18 }
19 {
20 // comptime call without comptime keyword
21 const result = @call(.{ .modifier = .compile_time }, foo, .{}) == 1234;
22 comptime try expect(result);
23 }
24 {
25 // call of non comptime-known function
26 var alias_foo = foo;
27 try expect(@call(.{ .modifier = .no_async }, alias_foo, .{}) == 1234);
28 try expect(@call(.{ .modifier = .never_tail }, alias_foo, .{}) == 1234);
29 try expect(@call(.{ .modifier = .never_inline }, alias_foo, .{}) == 1234);
30 }
31}
32
33test "tuple parameters" {
34 const add = struct {
35 fn add(a: i32, b: i32) i32 {
36 return a + b;
37 }
38 }.add;
39 var a: i32 = 12;
40 var b: i32 = 34;
41 try expect(@call(.{}, add, .{ a, 34 }) == 46);
42 try expect(@call(.{}, add, .{ 12, b }) == 46);
43 try expect(@call(.{}, add, .{ a, b }) == 46);
44 try expect(@call(.{}, add, .{ 12, 34 }) == 46);
45 comptime try expect(@call(.{}, add, .{ 12, 34 }) == 46);
46 {
47 const separate_args0 = .{ a, b };
48 const separate_args1 = .{ a, 34 };
49 const separate_args2 = .{ 12, 34 };
50 const separate_args3 = .{ 12, b };
51 try expect(@call(.{ .modifier = .always_inline }, add, separate_args0) == 46);
52 try expect(@call(.{ .modifier = .always_inline }, add, separate_args1) == 46);
53 try expect(@call(.{ .modifier = .always_inline }, add, separate_args2) == 46);
54 try expect(@call(.{ .modifier = .always_inline }, add, separate_args3) == 46);
55 }
56}
57
58test "comptime call with bound function as parameter" {
59 const S = struct {
60 fn ReturnType(func: anytype) type {
61 return switch (@typeInfo(@TypeOf(func))) {
62 .BoundFn => |info| info,
63 else => unreachable,
64 }.return_type orelse void;
65 }
66
67 fn call_me_maybe() ?i32 {
68 return 123;
69 }
70 };
71
72 var inst: S = undefined;
73 try expectEqual(?i32, S.ReturnType(inst.call_me_maybe));
74}
test/stage1/behavior/cast.zig deleted-926
...@@ -1,926 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4const maxInt = std.math.maxInt;
5const Vector = std.meta.Vector;
6
7test "int to ptr cast" {
8 const x = @as(usize, 13);
9 const y = @intToPtr(*u8, x);
10 const z = @ptrToInt(y);
11 try expect(z == 13);
12}
13
14test "integer literal to pointer cast" {
15 const vga_mem = @intToPtr(*u16, 0xB8000);
16 try expect(@ptrToInt(vga_mem) == 0xB8000);
17}
18
19test "pointer reinterpret const float to int" {
20 // The hex representation is 0x3fe3333333333303.
21 const float: f64 = 5.99999999999994648725e-01;
22 const float_ptr = &float;
23 const int_ptr = @ptrCast(*const i32, float_ptr);
24 const int_val = int_ptr.*;
25 if (std.builtin.endian == .Little)
26 try expect(int_val == 0x33333303)
27 else
28 try expect(int_val == 0x3fe33333);
29}
30
31test "implicitly cast indirect pointer to maybe-indirect pointer" {
32 const S = struct {
33 const Self = @This();
34 x: u8,
35 fn constConst(p: *const *const Self) u8 {
36 return p.*.x;
37 }
38 fn maybeConstConst(p: ?*const *const Self) u8 {
39 return p.?.*.x;
40 }
41 fn constConstConst(p: *const *const *const Self) u8 {
42 return p.*.*.x;
43 }
44 fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
45 return p.?.*.*.x;
46 }
47 };
48 const s = S{ .x = 42 };
49 const p = &s;
50 const q = &p;
51 const r = &q;
52 try expect(42 == S.constConst(q));
53 try expect(42 == S.maybeConstConst(q));
54 try expect(42 == S.constConstConst(r));
55 try expect(42 == S.maybeConstConstConst(r));
56}
57
58test "explicit cast from integer to error type" {
59 try testCastIntToErr(error.ItBroke);
60 comptime try testCastIntToErr(error.ItBroke);
61}
62fn testCastIntToErr(err: anyerror) !void {
63 const x = @errorToInt(err);
64 const y = @intToError(x);
65 try expect(error.ItBroke == y);
66}
67
68test "peer resolve arrays of different size to const slice" {
69 try expect(mem.eql(u8, boolToStr(true), "true"));
70 try expect(mem.eql(u8, boolToStr(false), "false"));
71 comptime try expect(mem.eql(u8, boolToStr(true), "true"));
72 comptime try expect(mem.eql(u8, boolToStr(false), "false"));
73}
74fn boolToStr(b: bool) []const u8 {
75 return if (b) "true" else "false";
76}
77
78test "peer resolve array and const slice" {
79 try testPeerResolveArrayConstSlice(true);
80 comptime try testPeerResolveArrayConstSlice(true);
81}
82fn testPeerResolveArrayConstSlice(b: bool) !void {
83 const value1 = if (b) "aoeu" else @as([]const u8, "zz");
84 const value2 = if (b) @as([]const u8, "zz") else "aoeu";
85 try expect(mem.eql(u8, value1, "aoeu"));
86 try expect(mem.eql(u8, value2, "zz"));
87}
88
89test "implicitly cast from T to anyerror!?T" {
90 try castToOptionalTypeError(1);
91 comptime try castToOptionalTypeError(1);
92}
93
94const A = struct {
95 a: i32,
96};
97fn castToOptionalTypeError(z: i32) !void {
98 const x = @as(i32, 1);
99 const y: anyerror!?i32 = x;
100 try expect((try y).? == 1);
101
102 const f = z;
103 const g: anyerror!?i32 = f;
104
105 const a = A{ .a = z };
106 const b: anyerror!?A = a;
107 try expect((b catch unreachable).?.a == 1);
108}
109
110test "implicitly cast from int to anyerror!?T" {
111 implicitIntLitToOptional();
112 comptime implicitIntLitToOptional();
113}
114fn implicitIntLitToOptional() void {
115 const f: ?i32 = 1;
116 const g: anyerror!?i32 = 1;
117}
118
119test "return null from fn() anyerror!?&T" {
120 const a = returnNullFromOptionalTypeErrorRef();
121 const b = returnNullLitFromOptionalTypeErrorRef();
122 try expect((try a) == null and (try b) == null);
123}
124fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
125 const a: ?*A = null;
126 return a;
127}
128fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
129 return null;
130}
131
132test "peer type resolution: ?T and T" {
133 try expect(peerTypeTAndOptionalT(true, false).? == 0);
134 try expect(peerTypeTAndOptionalT(false, false).? == 3);
135 comptime {
136 try expect(peerTypeTAndOptionalT(true, false).? == 0);
137 try expect(peerTypeTAndOptionalT(false, false).? == 3);
138 }
139}
140fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
141 if (c) {
142 return if (b) null else @as(usize, 0);
143 }
144
145 return @as(usize, 3);
146}
147
148test "peer type resolution: [0]u8 and []const u8" {
149 try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
150 try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
151 comptime {
152 try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
153 try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
154 }
155}
156fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
157 if (a) {
158 return &[_]u8{};
159 }
160
161 return slice[0..1];
162}
163
164test "implicitly cast from [N]T to ?[]const T" {
165 try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
166 comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
167}
168
169fn castToOptionalSlice() ?[]const u8 {
170 return "hi";
171}
172
173test "implicitly cast from [0]T to anyerror![]T" {
174 try testCastZeroArrayToErrSliceMut();
175 comptime try testCastZeroArrayToErrSliceMut();
176}
177
178fn testCastZeroArrayToErrSliceMut() !void {
179 try expect((gimmeErrOrSlice() catch unreachable).len == 0);
180}
181
182fn gimmeErrOrSlice() anyerror![]u8 {
183 return &[_]u8{};
184}
185
186test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
187 const S = struct {
188 fn doTheTest() anyerror!void {
189 {
190 var data = "hi".*;
191 const slice = data[0..];
192 try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
193 try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
194 }
195 {
196 var data: [2]u8 = "hi".*;
197 const slice = data[0..];
198 try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
199 try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
200 }
201 }
202 };
203 try S.doTheTest();
204 comptime try S.doTheTest();
205}
206fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
207 if (a) {
208 return &[_]u8{};
209 }
210
211 return slice[0..1];
212}
213
214test "resolve undefined with integer" {
215 try testResolveUndefWithInt(true, 1234);
216 comptime try testResolveUndefWithInt(true, 1234);
217}
218fn testResolveUndefWithInt(b: bool, x: i32) !void {
219 const value = if (b) x else undefined;
220 if (b) {
221 try expect(value == x);
222 }
223}
224
225test "implicit cast from &const [N]T to []const T" {
226 try testCastConstArrayRefToConstSlice();
227 comptime try testCastConstArrayRefToConstSlice();
228}
229
230fn testCastConstArrayRefToConstSlice() !void {
231 {
232 const blah = "aoeu".*;
233 const const_array_ref = &blah;
234 try expect(@TypeOf(const_array_ref) == *const [4:0]u8);
235 const slice: []const u8 = const_array_ref;
236 try expect(mem.eql(u8, slice, "aoeu"));
237 }
238 {
239 const blah: [4]u8 = "aoeu".*;
240 const const_array_ref = &blah;
241 try expect(@TypeOf(const_array_ref) == *const [4]u8);
242 const slice: []const u8 = const_array_ref;
243 try expect(mem.eql(u8, slice, "aoeu"));
244 }
245}
246
247test "peer type resolution: error and [N]T" {
248 try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
249 comptime try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
250 try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
251 comptime try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
252}
253
254fn testPeerErrorAndArray(x: u8) anyerror![]const u8 {
255 return switch (x) {
256 0x00 => "OK",
257 else => error.BadValue,
258 };
259}
260fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
261 return switch (x) {
262 0x00 => "OK",
263 0x01 => "OKK",
264 else => error.BadValue,
265 };
266}
267
268test "@floatToInt" {
269 try testFloatToInts();
270 comptime try testFloatToInts();
271}
272
273fn testFloatToInts() !void {
274 const x = @as(i32, 1e4);
275 try expect(x == 10000);
276 const y = @floatToInt(i32, @as(f32, 1e4));
277 try expect(y == 10000);
278 try expectFloatToInt(f16, 255.1, u8, 255);
279 try expectFloatToInt(f16, 127.2, i8, 127);
280 try expectFloatToInt(f16, -128.2, i8, -128);
281 try expectFloatToInt(f32, 255.1, u8, 255);
282 try expectFloatToInt(f32, 127.2, i8, 127);
283 try expectFloatToInt(f32, -128.2, i8, -128);
284 try expectFloatToInt(comptime_int, 1234, i16, 1234);
285}
286
287fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
288 try expect(@floatToInt(I, f) == i);
289}
290
291test "cast u128 to f128 and back" {
292 comptime try testCast128();
293 try testCast128();
294}
295
296fn testCast128() !void {
297 try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
298}
299
300fn cast128Int(x: f128) u128 {
301 return @bitCast(u128, x);
302}
303
304fn cast128Float(x: u128) f128 {
305 return @bitCast(f128, x);
306}
307
308test "single-item pointer of array to slice and to unknown length pointer" {
309 try testCastPtrOfArrayToSliceAndPtr();
310 comptime try testCastPtrOfArrayToSliceAndPtr();
311}
312
313fn testCastPtrOfArrayToSliceAndPtr() !void {
314 {
315 var array = "aoeu".*;
316 const x: [*]u8 = &array;
317 x[0] += 1;
318 try expect(mem.eql(u8, array[0..], "boeu"));
319 const y: []u8 = &array;
320 y[0] += 1;
321 try expect(mem.eql(u8, array[0..], "coeu"));
322 }
323 {
324 var array: [4]u8 = "aoeu".*;
325 const x: [*]u8 = &array;
326 x[0] += 1;
327 try expect(mem.eql(u8, array[0..], "boeu"));
328 const y: []u8 = &array;
329 y[0] += 1;
330 try expect(mem.eql(u8, array[0..], "coeu"));
331 }
332}
333
334test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
335 const window_name = [1][*]const u8{"window name"};
336 const x: [*]const ?[*]const u8 = &window_name;
337 try expect(mem.eql(u8, std.mem.spanZ(@ptrCast([*:0]const u8, x[0].?)), "window name"));
338}
339
340test "@intCast comptime_int" {
341 const result = @intCast(i32, 1234);
342 try expect(@TypeOf(result) == i32);
343 try expect(result == 1234);
344}
345
346test "@floatCast comptime_int and comptime_float" {
347 {
348 const result = @floatCast(f16, 1234);
349 try expect(@TypeOf(result) == f16);
350 try expect(result == 1234.0);
351 }
352 {
353 const result = @floatCast(f16, 1234.0);
354 try expect(@TypeOf(result) == f16);
355 try expect(result == 1234.0);
356 }
357 {
358 const result = @floatCast(f32, 1234);
359 try expect(@TypeOf(result) == f32);
360 try expect(result == 1234.0);
361 }
362 {
363 const result = @floatCast(f32, 1234.0);
364 try expect(@TypeOf(result) == f32);
365 try expect(result == 1234.0);
366 }
367}
368
369test "vector casts" {
370 const S = struct {
371 fn doTheTest() !void {
372 // Upcast (implicit, equivalent to @intCast)
373 var up0: Vector(2, u8) = [_]u8{ 0x55, 0xaa };
374 var up1 = @as(Vector(2, u16), up0);
375 var up2 = @as(Vector(2, u32), up0);
376 var up3 = @as(Vector(2, u64), up0);
377 // Downcast (safety-checked)
378 var down0 = up3;
379 var down1 = @intCast(Vector(2, u32), down0);
380 var down2 = @intCast(Vector(2, u16), down0);
381 var down3 = @intCast(Vector(2, u8), down0);
382
383 try expect(mem.eql(u16, &@as([2]u16, up1), &[2]u16{ 0x55, 0xaa }));
384 try expect(mem.eql(u32, &@as([2]u32, up2), &[2]u32{ 0x55, 0xaa }));
385 try expect(mem.eql(u64, &@as([2]u64, up3), &[2]u64{ 0x55, 0xaa }));
386
387 try expect(mem.eql(u32, &@as([2]u32, down1), &[2]u32{ 0x55, 0xaa }));
388 try expect(mem.eql(u16, &@as([2]u16, down2), &[2]u16{ 0x55, 0xaa }));
389 try expect(mem.eql(u8, &@as([2]u8, down3), &[2]u8{ 0x55, 0xaa }));
390 }
391
392 fn doTheTestFloat() !void {
393 var vec = @splat(2, @as(f32, 1234.0));
394 var wider: Vector(2, f64) = vec;
395 try expect(wider[0] == 1234.0);
396 try expect(wider[1] == 1234.0);
397 }
398 };
399
400 try S.doTheTest();
401 comptime try S.doTheTest();
402 try S.doTheTestFloat();
403 comptime try S.doTheTestFloat();
404}
405
406test "comptime_int @intToFloat" {
407 {
408 const result = @intToFloat(f16, 1234);
409 try expect(@TypeOf(result) == f16);
410 try expect(result == 1234.0);
411 }
412 {
413 const result = @intToFloat(f32, 1234);
414 try expect(@TypeOf(result) == f32);
415 try expect(result == 1234.0);
416 }
417 {
418 const result = @intToFloat(f64, 1234);
419 try expect(@TypeOf(result) == f64);
420 try expect(result == 1234.0);
421 }
422 {
423 const result = @intToFloat(f128, 1234);
424 try expect(@TypeOf(result) == f128);
425 try expect(result == 1234.0);
426 }
427 // big comptime_int (> 64 bits) to f128 conversion
428 {
429 const result = @intToFloat(f128, 0x1_0000_0000_0000_0000);
430 try expect(@TypeOf(result) == f128);
431 try expect(result == 0x1_0000_0000_0000_0000.0);
432 }
433}
434
435test "@intCast i32 to u7" {
436 var x: u128 = maxInt(u128);
437 var y: i32 = 120;
438 var z = x >> @intCast(u7, y);
439 try expect(z == 0xff);
440}
441
442test "@floatCast cast down" {
443 {
444 var double: f64 = 0.001534;
445 var single = @floatCast(f32, double);
446 try expect(single == 0.001534);
447 }
448 {
449 const double: f64 = 0.001534;
450 const single = @floatCast(f32, double);
451 try expect(single == 0.001534);
452 }
453}
454
455test "implicit cast undefined to optional" {
456 try expect(MakeType(void).getNull() == null);
457 try expect(MakeType(void).getNonNull() != null);
458}
459
460fn MakeType(comptime T: type) type {
461 return struct {
462 fn getNull() ?T {
463 return null;
464 }
465
466 fn getNonNull() ?T {
467 return @as(T, undefined);
468 }
469 };
470}
471
472test "implicit cast from *[N]T to ?[*]T" {
473 var x: ?[*]u16 = null;
474 var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
475
476 x = &y;
477 try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
478 x.?[0] = 8;
479 y[3] = 6;
480 try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
481}
482
483test "implicit cast from *[N]T to [*c]T" {
484 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
485 var y: [*c]u16 = &x;
486
487 try expect(std.mem.eql(u16, x[0..4], y[0..4]));
488 x[0] = 8;
489 y[3] = 6;
490 try expect(std.mem.eql(u16, x[0..4], y[0..4]));
491}
492
493test "implicit cast from *T to ?*c_void" {
494 var a: u8 = 1;
495 incrementVoidPtrValue(&a);
496 try std.testing.expect(a == 2);
497}
498
499fn incrementVoidPtrValue(value: ?*c_void) void {
500 @ptrCast(*u8, value.?).* += 1;
501}
502
503test "implicit cast from [*]T to ?*c_void" {
504 var a = [_]u8{ 3, 2, 1 };
505 var runtime_zero: usize = 0;
506 incrementVoidPtrArray(a[runtime_zero..].ptr, 3);
507 try expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 }));
508}
509
510fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
511 var n: usize = 0;
512 while (n < len) : (n += 1) {
513 @ptrCast([*]u8, array.?)[n] += 1;
514 }
515}
516
517test "*usize to *void" {
518 var i = @as(usize, 0);
519 var v = @ptrCast(*void, &i);
520 v.* = {};
521}
522
523test "compile time int to ptr of function" {
524 try foobar(FUNCTION_CONSTANT);
525}
526
527pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
528pub const PFN_void = fn (*c_void) callconv(.C) void;
529
530fn foobar(func: PFN_void) !void {
531 try std.testing.expect(@ptrToInt(func) == maxInt(usize));
532}
533
534test "implicit ptr to *c_void" {
535 var a: u32 = 1;
536 var ptr: *align(@alignOf(u32)) c_void = &a;
537 var b: *u32 = @ptrCast(*u32, ptr);
538 try expect(b.* == 1);
539 var ptr2: ?*align(@alignOf(u32)) c_void = &a;
540 var c: *u32 = @ptrCast(*u32, ptr2.?);
541 try expect(c.* == 1);
542}
543
544test "@intCast to comptime_int" {
545 try expect(@intCast(comptime_int, 0) == 0);
546}
547
548test "implicit cast comptime numbers to any type when the value fits" {
549 const a: u64 = 255;
550 var b: u8 = a;
551 try expect(b == 255);
552}
553
554test "@intToEnum passed a comptime_int to an enum with one item" {
555 const E = enum {
556 A,
557 };
558 const x = @intToEnum(E, 0);
559 try expect(x == E.A);
560}
561
562test "@intToEnum runtime to an extern enum with duplicate values" {
563 const E = extern enum(u8) {
564 A = 1,
565 B = 1,
566 };
567 var a: u8 = 1;
568 var x = @intToEnum(E, a);
569 try expect(x == E.A);
570 try expect(x == E.B);
571}
572
573test "@intCast to u0 and use the result" {
574 const S = struct {
575 fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {
576 try expect((one << @intCast(u0, bigzero)) == 1);
577 try expect((zero << @intCast(u0, bigzero)) == 0);
578 }
579 };
580 try S.doTheTest(0, 1, 0);
581 comptime try S.doTheTest(0, 1, 0);
582}
583
584test "peer type resolution: unreachable, null, slice" {
585 const S = struct {
586 fn doTheTest(num: usize, word: []const u8) !void {
587 const result = switch (num) {
588 0 => null,
589 1 => word,
590 else => unreachable,
591 };
592 try expect(mem.eql(u8, result.?, "hi"));
593 }
594 };
595 try S.doTheTest(1, "hi");
596}
597
598test "peer type resolution: unreachable, error set, unreachable" {
599 const Error = error{
600 FileDescriptorAlreadyPresentInSet,
601 OperationCausesCircularLoop,
602 FileDescriptorNotRegistered,
603 SystemResources,
604 UserResourceLimitReached,
605 FileDescriptorIncompatibleWithEpoll,
606 Unexpected,
607 };
608 var err = Error.SystemResources;
609 const transformed_err = switch (err) {
610 error.FileDescriptorAlreadyPresentInSet => unreachable,
611 error.OperationCausesCircularLoop => unreachable,
612 error.FileDescriptorNotRegistered => unreachable,
613 error.SystemResources => error.SystemResources,
614 error.UserResourceLimitReached => error.UserResourceLimitReached,
615 error.FileDescriptorIncompatibleWithEpoll => unreachable,
616 error.Unexpected => unreachable,
617 };
618 try expect(transformed_err == error.SystemResources);
619}
620
621test "implicit cast comptime_int to comptime_float" {
622 comptime try expect(@as(comptime_float, 10) == @as(f32, 10));
623 try expect(2 == 2.0);
624}
625
626test "implicit cast *[0]T to E![]const u8" {
627 var x = @as(anyerror![]const u8, &[0]u8{});
628 try expect((x catch unreachable).len == 0);
629}
630
631test "peer cast *[0]T to E![]const T" {
632 var buffer: [5]u8 = "abcde".*;
633 var buf: anyerror![]const u8 = buffer[0..];
634 var b = false;
635 var y = if (b) &[0]u8{} else buf;
636 try expect(mem.eql(u8, "abcde", y catch unreachable));
637}
638
639test "peer cast *[0]T to []const T" {
640 var buffer: [5]u8 = "abcde".*;
641 var buf: []const u8 = buffer[0..];
642 var b = false;
643 var y = if (b) &[0]u8{} else buf;
644 try expect(mem.eql(u8, "abcde", y));
645}
646
647var global_array: [4]u8 = undefined;
648test "cast from array reference to fn" {
649 const f = @ptrCast(fn () callconv(.C) void, &global_array);
650 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
651}
652
653test "*const [N]null u8 to ?[]const u8" {
654 const S = struct {
655 fn doTheTest() !void {
656 var a = "Hello";
657 var b: ?[]const u8 = a;
658 try expect(mem.eql(u8, b.?, "Hello"));
659 }
660 };
661 try S.doTheTest();
662 comptime try S.doTheTest();
663}
664
665test "peer resolution of string literals" {
666 const S = struct {
667 const E = extern enum {
668 a,
669 b,
670 c,
671 d,
672 };
673
674 fn doTheTest(e: E) !void {
675 const cmd = switch (e) {
676 .a => "one",
677 .b => "two",
678 .c => "three",
679 .d => "four",
680 };
681 try expect(mem.eql(u8, cmd, "two"));
682 }
683 };
684 try S.doTheTest(.b);
685 comptime try S.doTheTest(.b);
686}
687
688test "type coercion related to sentinel-termination" {
689 const S = struct {
690 fn doTheTest() !void {
691 // [:x]T to []T
692 {
693 var array = [4:0]i32{ 1, 2, 3, 4 };
694 var slice: [:0]i32 = &array;
695 var dest: []i32 = slice;
696 try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
697 }
698
699 // [*:x]T to [*]T
700 {
701 var array = [4:99]i32{ 1, 2, 3, 4 };
702 var dest: [*]i32 = &array;
703 try expect(dest[0] == 1);
704 try expect(dest[1] == 2);
705 try expect(dest[2] == 3);
706 try expect(dest[3] == 4);
707 try expect(dest[4] == 99);
708 }
709
710 // [N:x]T to [N]T
711 {
712 var array = [4:0]i32{ 1, 2, 3, 4 };
713 var dest: [4]i32 = array;
714 try expect(mem.eql(i32, &dest, &[_]i32{ 1, 2, 3, 4 }));
715 }
716
717 // *[N:x]T to *[N]T
718 {
719 var array = [4:0]i32{ 1, 2, 3, 4 };
720 var dest: *[4]i32 = &array;
721 try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
722 }
723
724 // [:x]T to [*:x]T
725 {
726 var array = [4:0]i32{ 1, 2, 3, 4 };
727 var slice: [:0]i32 = &array;
728 var dest: [*:0]i32 = slice;
729 try expect(dest[0] == 1);
730 try expect(dest[1] == 2);
731 try expect(dest[2] == 3);
732 try expect(dest[3] == 4);
733 try expect(dest[4] == 0);
734 }
735 }
736 };
737 try S.doTheTest();
738 comptime try S.doTheTest();
739}
740
741test "cast i8 fn call peers to i32 result" {
742 const S = struct {
743 fn doTheTest() !void {
744 var cond = true;
745 const value: i32 = if (cond) smallBoi() else bigBoi();
746 try expect(value == 123);
747 }
748 fn smallBoi() i8 {
749 return 123;
750 }
751 fn bigBoi() i16 {
752 return 1234;
753 }
754 };
755 try S.doTheTest();
756 comptime try S.doTheTest();
757}
758
759test "return u8 coercing into ?u32 return type" {
760 const S = struct {
761 fn doTheTest() !void {
762 try expect(foo(123).? == 123);
763 }
764 fn foo(arg: u8) ?u32 {
765 return arg;
766 }
767 };
768 try S.doTheTest();
769 comptime try S.doTheTest();
770}
771
772test "peer result null and comptime_int" {
773 const S = struct {
774 fn blah(n: i32) ?i32 {
775 if (n == 0) {
776 return null;
777 } else if (n < 0) {
778 return -1;
779 } else {
780 return 1;
781 }
782 }
783 };
784
785 try expect(S.blah(0) == null);
786 comptime try expect(S.blah(0) == null);
787 try expect(S.blah(10).? == 1);
788 comptime try expect(S.blah(10).? == 1);
789 try expect(S.blah(-10).? == -1);
790 comptime try expect(S.blah(-10).? == -1);
791}
792
793test "peer type resolution implicit cast to return type" {
794 const S = struct {
795 fn doTheTest() !void {
796 for ("hello") |c| _ = f(c);
797 }
798 fn f(c: u8) []const u8 {
799 return switch (c) {
800 'h', 'e' => &[_]u8{c}, // should cast to slice
801 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
802 else => ([_]u8{c})[0..], // is a slice
803 };
804 }
805 };
806 try S.doTheTest();
807 comptime try S.doTheTest();
808}
809
810test "peer type resolution implicit cast to variable type" {
811 const S = struct {
812 fn doTheTest() !void {
813 var x: []const u8 = undefined;
814 for ("hello") |c| x = switch (c) {
815 'h', 'e' => &[_]u8{c}, // should cast to slice
816 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
817 else => ([_]u8{c})[0..], // is a slice
818 };
819 }
820 };
821 try S.doTheTest();
822 comptime try S.doTheTest();
823}
824
825test "variable initialization uses result locations properly with regards to the type" {
826 var b = true;
827 const x: i32 = if (b) 1 else 2;
828 try expect(x == 1);
829}
830
831test "cast between [*c]T and ?[*:0]T on fn parameter" {
832 const S = struct {
833 const Handler = ?fn ([*c]const u8) callconv(.C) void;
834 fn addCallback(handler: Handler) void {}
835
836 fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void {}
837
838 fn doTheTest() void {
839 addCallback(myCallback);
840 }
841 };
842 S.doTheTest();
843}
844
845test "cast between C pointer with different but compatible types" {
846 const S = struct {
847 fn foo(arg: [*]c_ushort) u16 {
848 return arg[0];
849 }
850 fn doTheTest() !void {
851 var x = [_]u16{ 4, 2, 1, 3 };
852 try expect(foo(@ptrCast([*]u16, &x)) == 4);
853 }
854 };
855 try S.doTheTest();
856}
857
858var global_struct: struct { f0: usize } = undefined;
859
860test "assignment to optional pointer result loc" {
861 var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
862 try expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
863}
864
865test "peer type resolve string lit with sentinel-terminated mutable slice" {
866 var array: [4:0]u8 = undefined;
867 array[4] = 0; // TODO remove this when #4372 is solved
868 var slice: [:0]u8 = array[0..4 :0];
869 comptime try expect(@TypeOf(slice, "hi") == [:0]const u8);
870 comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
871}
872
873test "peer type unsigned int to signed" {
874 var w: u31 = 5;
875 var x: u8 = 7;
876 var y: i32 = -5;
877 var a = w + y + x;
878 comptime try expect(@TypeOf(a) == i32);
879 try expect(a == 7);
880}
881
882test "peer type resolve array pointers, one of them const" {
883 var array1: [4]u8 = undefined;
884 const array2: [5]u8 = undefined;
885 comptime try expect(@TypeOf(&array1, &array2) == []const u8);
886 comptime try expect(@TypeOf(&array2, &array1) == []const u8);
887}
888
889test "peer type resolve array pointer and unknown pointer" {
890 const const_array: [4]u8 = undefined;
891 var array: [4]u8 = undefined;
892 var const_ptr: [*]const u8 = undefined;
893 var ptr: [*]u8 = undefined;
894
895 comptime try expect(@TypeOf(&array, ptr) == [*]u8);
896 comptime try expect(@TypeOf(ptr, &array) == [*]u8);
897
898 comptime try expect(@TypeOf(&const_array, ptr) == [*]const u8);
899 comptime try expect(@TypeOf(ptr, &const_array) == [*]const u8);
900
901 comptime try expect(@TypeOf(&array, const_ptr) == [*]const u8);
902 comptime try expect(@TypeOf(const_ptr, &array) == [*]const u8);
903
904 comptime try expect(@TypeOf(&const_array, const_ptr) == [*]const u8);
905 comptime try expect(@TypeOf(const_ptr, &const_array) == [*]const u8);
906}
907
908test "comptime float casts" {
909 const a = @intToFloat(comptime_float, 1);
910 try expect(a == 1);
911 try expect(@TypeOf(a) == comptime_float);
912 const b = @floatToInt(comptime_int, 2);
913 try expect(b == 2);
914 try expect(@TypeOf(b) == comptime_int);
915}
916
917test "cast from ?[*]T to ??[*]T" {
918 const a: ??[*]u8 = @as(?[*]u8, null);
919 try expect(a != null and a.? == null);
920}
921
922test "cast between *[N]void and []void" {
923 var a: [4]void = undefined;
924 var b: []void = &a;
925 try expect(b.len == 4);
926}
test/stage1/behavior/const_slice_child.zig deleted-47
...@@ -1,47 +0,0 @@
1const std = @import("std");
2const debug = std.debug;
3const testing = std.testing;
4const expect = testing.expect;
5
6var argv: [*]const [*]const u8 = undefined;
7
8test "const slice child" {
9 const strs = [_][*]const u8{
10 "one",
11 "two",
12 "three",
13 };
14 argv = &strs;
15 try bar(strs.len);
16}
17
18fn foo(args: [][]const u8) !void {
19 try expect(args.len == 3);
20 try expect(streql(args[0], "one"));
21 try expect(streql(args[1], "two"));
22 try expect(streql(args[2], "three"));
23}
24
25fn bar(argc: usize) !void {
26 const args = testing.allocator.alloc([]const u8, argc) catch unreachable;
27 defer testing.allocator.free(args);
28 for (args) |_, i| {
29 const ptr = argv[i];
30 args[i] = ptr[0..strlen(ptr)];
31 }
32 try foo(args);
33}
34
35fn strlen(ptr: [*]const u8) usize {
36 var count: usize = 0;
37 while (ptr[count] != 0) : (count += 1) {}
38 return count;
39}
40
41fn streql(a: []const u8, b: []const u8) bool {
42 if (a.len != b.len) return false;
43 for (a) |item, index| {
44 if (b[index] != item) return false;
45 }
46 return true;
47}
test/stage1/behavior/defer.zig deleted-114
...@@ -1,114 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const expectError = std.testing.expectError;
5
6var result: [3]u8 = undefined;
7var index: usize = undefined;
8
9fn runSomeErrorDefers(x: bool) !bool {
10 index = 0;
11 defer {
12 result[index] = 'a';
13 index += 1;
14 }
15 errdefer {
16 result[index] = 'b';
17 index += 1;
18 }
19 defer {
20 result[index] = 'c';
21 index += 1;
22 }
23 return if (x) x else error.FalseNotAllowed;
24}
25
26test "mixing normal and error defers" {
27 try expect(runSomeErrorDefers(true) catch unreachable);
28 try expect(result[0] == 'c');
29 try expect(result[1] == 'a');
30
31 const ok = runSomeErrorDefers(false) catch |err| x: {
32 try expect(err == error.FalseNotAllowed);
33 break :x true;
34 };
35 try expect(ok);
36 try expect(result[0] == 'c');
37 try expect(result[1] == 'b');
38 try expect(result[2] == 'a');
39}
40
41test "break and continue inside loop inside defer expression" {
42 testBreakContInDefer(10);
43 comptime testBreakContInDefer(10);
44}
45
46fn testBreakContInDefer(x: usize) void {
47 defer {
48 var i: usize = 0;
49 while (i < x) : (i += 1) {
50 if (i < 5) continue;
51 if (i == 5) break;
52 }
53 expect(i == 5) catch @panic("test failure");
54 }
55}
56
57test "defer and labeled break" {
58 var i = @as(usize, 0);
59
60 blk: {
61 defer i += 1;
62 break :blk;
63 }
64
65 try expect(i == 1);
66}
67
68test "errdefer does not apply to fn inside fn" {
69 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| try expect(e == error.Bad);
70}
71
72fn testNestedFnErrDefer() anyerror!void {
73 var a: i32 = 0;
74 errdefer a += 1;
75 const S = struct {
76 fn baz() anyerror {
77 return error.Bad;
78 }
79 };
80 return S.baz();
81}
82
83test "return variable while defer expression in scope to modify it" {
84 const S = struct {
85 fn doTheTest() !void {
86 try expect(notNull().? == 1);
87 }
88
89 fn notNull() ?u8 {
90 var res: ?u8 = 1;
91 defer res = null;
92 return res;
93 }
94 };
95
96 try S.doTheTest();
97 comptime try S.doTheTest();
98}
99
100test "errdefer with payload" {
101 const S = struct {
102 fn foo() !i32 {
103 errdefer |a| {
104 expectEqual(error.One, a) catch @panic("test failure");
105 }
106 return error.One;
107 }
108 fn doTheTest() !void {
109 try expectError(error.One, foo());
110 }
111 };
112 try S.doTheTest();
113 comptime try S.doTheTest();
114}
test/stage1/behavior/enum.zig deleted-1204
...@@ -1,1204 +0,0 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3const Tag = @import("std").meta.Tag;
4
5test "extern enum" {
6 const S = struct {
7 const i = extern enum {
8 n = 0,
9 o = 2,
10 p = 4,
11 q = 4,
12 };
13 fn doTheTest(y: c_int) void {
14 var x = i.o;
15 switch (x) {
16 .n, .p => unreachable,
17 .o => {},
18 }
19 }
20 };
21 S.doTheTest(52);
22 comptime S.doTheTest(52);
23}
24
25test "non-exhaustive enum" {
26 const S = struct {
27 const E = enum(u8) {
28 a,
29 b,
30 _,
31 };
32 fn doTheTest(y: u8) !void {
33 var e: E = .b;
34 try expect(switch (e) {
35 .a => false,
36 .b => true,
37 _ => false,
38 });
39 e = @intToEnum(E, 12);
40 try expect(switch (e) {
41 .a => false,
42 .b => false,
43 _ => true,
44 });
45
46 try expect(switch (e) {
47 .a => false,
48 .b => false,
49 else => true,
50 });
51 e = .b;
52 try expect(switch (e) {
53 .a => false,
54 else => true,
55 });
56
57 try expect(@typeInfo(E).Enum.fields.len == 2);
58 e = @intToEnum(E, 12);
59 try expect(@enumToInt(e) == 12);
60 e = @intToEnum(E, y);
61 try expect(@enumToInt(e) == 52);
62 try expect(@typeInfo(E).Enum.is_exhaustive == false);
63 }
64 };
65 try S.doTheTest(52);
66 comptime try S.doTheTest(52);
67}
68
69test "empty non-exhaustive enum" {
70 const S = struct {
71 const E = enum(u8) {
72 _,
73 };
74 fn doTheTest(y: u8) !void {
75 var e = @intToEnum(E, y);
76 try expect(switch (e) {
77 _ => true,
78 });
79 try expect(@enumToInt(e) == y);
80
81 try expect(@typeInfo(E).Enum.fields.len == 0);
82 try expect(@typeInfo(E).Enum.is_exhaustive == false);
83 }
84 };
85 try S.doTheTest(42);
86 comptime try S.doTheTest(42);
87}
88
89test "single field non-exhaustive enum" {
90 const S = struct {
91 const E = enum(u8) {
92 a,
93 _,
94 };
95 fn doTheTest(y: u8) !void {
96 var e: E = .a;
97 try expect(switch (e) {
98 .a => true,
99 _ => false,
100 });
101 e = @intToEnum(E, 12);
102 try expect(switch (e) {
103 .a => false,
104 _ => true,
105 });
106
107 try expect(switch (e) {
108 .a => false,
109 else => true,
110 });
111 e = .a;
112 try expect(switch (e) {
113 .a => true,
114 else => false,
115 });
116
117 try expect(@enumToInt(@intToEnum(E, y)) == y);
118 try expect(@typeInfo(E).Enum.fields.len == 1);
119 try expect(@typeInfo(E).Enum.is_exhaustive == false);
120 }
121 };
122 try S.doTheTest(23);
123 comptime try S.doTheTest(23);
124}
125
126test "enum type" {
127 const foo1 = Foo{ .One = 13 };
128 const foo2 = Foo{
129 .Two = Point{
130 .x = 1234,
131 .y = 5678,
132 },
133 };
134 const bar = Bar.B;
135
136 try expect(bar == Bar.B);
137 try expect(@typeInfo(Foo).Union.fields.len == 3);
138 try expect(@typeInfo(Bar).Enum.fields.len == 4);
139 try expect(@sizeOf(Foo) == @sizeOf(FooNoVoid));
140 try expect(@sizeOf(Bar) == 1);
141}
142
143test "enum as return value" {
144 switch (returnAnInt(13)) {
145 Foo.One => |value| try expect(value == 13),
146 else => unreachable,
147 }
148}
149
150const Point = struct {
151 x: u64,
152 y: u64,
153};
154const Foo = union(enum) {
155 One: i32,
156 Two: Point,
157 Three: void,
158};
159const FooNoVoid = union(enum) {
160 One: i32,
161 Two: Point,
162};
163const Bar = enum {
164 A,
165 B,
166 C,
167 D,
168};
169
170fn returnAnInt(x: i32) Foo {
171 return Foo{ .One = x };
172}
173
174test "constant enum with payload" {
175 var empty = AnEnumWithPayload{ .Empty = {} };
176 var full = AnEnumWithPayload{ .Full = 13 };
177 shouldBeEmpty(empty);
178 shouldBeNotEmpty(full);
179}
180
181fn shouldBeEmpty(x: AnEnumWithPayload) void {
182 switch (x) {
183 AnEnumWithPayload.Empty => {},
184 else => unreachable,
185 }
186}
187
188fn shouldBeNotEmpty(x: AnEnumWithPayload) void {
189 switch (x) {
190 AnEnumWithPayload.Empty => unreachable,
191 else => {},
192 }
193}
194
195const AnEnumWithPayload = union(enum) {
196 Empty: void,
197 Full: i32,
198};
199
200const Number = enum {
201 Zero,
202 One,
203 Two,
204 Three,
205 Four,
206};
207
208test "enum to int" {
209 try shouldEqual(Number.Zero, 0);
210 try shouldEqual(Number.One, 1);
211 try shouldEqual(Number.Two, 2);
212 try shouldEqual(Number.Three, 3);
213 try shouldEqual(Number.Four, 4);
214}
215
216fn shouldEqual(n: Number, expected: u3) !void {
217 try expect(@enumToInt(n) == expected);
218}
219
220test "int to enum" {
221 try testIntToEnumEval(3);
222}
223fn testIntToEnumEval(x: i32) !void {
224 try expect(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
225}
226const IntToEnumNumber = enum {
227 Zero,
228 One,
229 Two,
230 Three,
231 Four,
232};
233
234test "@tagName" {
235 try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
236 comptime try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
237}
238
239test "@tagName extern enum with duplicates" {
240 try expect(mem.eql(u8, testEnumTagNameBare(ExternDuplicates.B), "A"));
241 comptime try expect(mem.eql(u8, testEnumTagNameBare(ExternDuplicates.B), "A"));
242}
243
244test "@tagName non-exhaustive enum" {
245 try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
246 comptime try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
247}
248
249fn testEnumTagNameBare(n: anytype) []const u8 {
250 return @tagName(n);
251}
252
253const BareNumber = enum {
254 One,
255 Two,
256 Three,
257};
258
259const ExternDuplicates = extern enum(u8) {
260 A = 1,
261 B = 1,
262};
263
264const NonExhaustive = enum(u8) {
265 A,
266 B,
267 _,
268};
269
270test "enum alignment" {
271 comptime {
272 try expect(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
273 try expect(@alignOf(AlignTestEnum) >= @alignOf(u64));
274 }
275}
276
277const AlignTestEnum = union(enum) {
278 A: [9]u8,
279 B: u64,
280};
281
282const ValueCount1 = enum {
283 I0,
284};
285const ValueCount2 = enum {
286 I0,
287 I1,
288};
289const ValueCount256 = enum {
290 I0,
291 I1,
292 I2,
293 I3,
294 I4,
295 I5,
296 I6,
297 I7,
298 I8,
299 I9,
300 I10,
301 I11,
302 I12,
303 I13,
304 I14,
305 I15,
306 I16,
307 I17,
308 I18,
309 I19,
310 I20,
311 I21,
312 I22,
313 I23,
314 I24,
315 I25,
316 I26,
317 I27,
318 I28,
319 I29,
320 I30,
321 I31,
322 I32,
323 I33,
324 I34,
325 I35,
326 I36,
327 I37,
328 I38,
329 I39,
330 I40,
331 I41,
332 I42,
333 I43,
334 I44,
335 I45,
336 I46,
337 I47,
338 I48,
339 I49,
340 I50,
341 I51,
342 I52,
343 I53,
344 I54,
345 I55,
346 I56,
347 I57,
348 I58,
349 I59,
350 I60,
351 I61,
352 I62,
353 I63,
354 I64,
355 I65,
356 I66,
357 I67,
358 I68,
359 I69,
360 I70,
361 I71,
362 I72,
363 I73,
364 I74,
365 I75,
366 I76,
367 I77,
368 I78,
369 I79,
370 I80,
371 I81,
372 I82,
373 I83,
374 I84,
375 I85,
376 I86,
377 I87,
378 I88,
379 I89,
380 I90,
381 I91,
382 I92,
383 I93,
384 I94,
385 I95,
386 I96,
387 I97,
388 I98,
389 I99,
390 I100,
391 I101,
392 I102,
393 I103,
394 I104,
395 I105,
396 I106,
397 I107,
398 I108,
399 I109,
400 I110,
401 I111,
402 I112,
403 I113,
404 I114,
405 I115,
406 I116,
407 I117,
408 I118,
409 I119,
410 I120,
411 I121,
412 I122,
413 I123,
414 I124,
415 I125,
416 I126,
417 I127,
418 I128,
419 I129,
420 I130,
421 I131,
422 I132,
423 I133,
424 I134,
425 I135,
426 I136,
427 I137,
428 I138,
429 I139,
430 I140,
431 I141,
432 I142,
433 I143,
434 I144,
435 I145,
436 I146,
437 I147,
438 I148,
439 I149,
440 I150,
441 I151,
442 I152,
443 I153,
444 I154,
445 I155,
446 I156,
447 I157,
448 I158,
449 I159,
450 I160,
451 I161,
452 I162,
453 I163,
454 I164,
455 I165,
456 I166,
457 I167,
458 I168,
459 I169,
460 I170,
461 I171,
462 I172,
463 I173,
464 I174,
465 I175,
466 I176,
467 I177,
468 I178,
469 I179,
470 I180,
471 I181,
472 I182,
473 I183,
474 I184,
475 I185,
476 I186,
477 I187,
478 I188,
479 I189,
480 I190,
481 I191,
482 I192,
483 I193,
484 I194,
485 I195,
486 I196,
487 I197,
488 I198,
489 I199,
490 I200,
491 I201,
492 I202,
493 I203,
494 I204,
495 I205,
496 I206,
497 I207,
498 I208,
499 I209,
500 I210,
501 I211,
502 I212,
503 I213,
504 I214,
505 I215,
506 I216,
507 I217,
508 I218,
509 I219,
510 I220,
511 I221,
512 I222,
513 I223,
514 I224,
515 I225,
516 I226,
517 I227,
518 I228,
519 I229,
520 I230,
521 I231,
522 I232,
523 I233,
524 I234,
525 I235,
526 I236,
527 I237,
528 I238,
529 I239,
530 I240,
531 I241,
532 I242,
533 I243,
534 I244,
535 I245,
536 I246,
537 I247,
538 I248,
539 I249,
540 I250,
541 I251,
542 I252,
543 I253,
544 I254,
545 I255,
546};
547const ValueCount257 = enum {
548 I0,
549 I1,
550 I2,
551 I3,
552 I4,
553 I5,
554 I6,
555 I7,
556 I8,
557 I9,
558 I10,
559 I11,
560 I12,
561 I13,
562 I14,
563 I15,
564 I16,
565 I17,
566 I18,
567 I19,
568 I20,
569 I21,
570 I22,
571 I23,
572 I24,
573 I25,
574 I26,
575 I27,
576 I28,
577 I29,
578 I30,
579 I31,
580 I32,
581 I33,
582 I34,
583 I35,
584 I36,
585 I37,
586 I38,
587 I39,
588 I40,
589 I41,
590 I42,
591 I43,
592 I44,
593 I45,
594 I46,
595 I47,
596 I48,
597 I49,
598 I50,
599 I51,
600 I52,
601 I53,
602 I54,
603 I55,
604 I56,
605 I57,
606 I58,
607 I59,
608 I60,
609 I61,
610 I62,
611 I63,
612 I64,
613 I65,
614 I66,
615 I67,
616 I68,
617 I69,
618 I70,
619 I71,
620 I72,
621 I73,
622 I74,
623 I75,
624 I76,
625 I77,
626 I78,
627 I79,
628 I80,
629 I81,
630 I82,
631 I83,
632 I84,
633 I85,
634 I86,
635 I87,
636 I88,
637 I89,
638 I90,
639 I91,
640 I92,
641 I93,
642 I94,
643 I95,
644 I96,
645 I97,
646 I98,
647 I99,
648 I100,
649 I101,
650 I102,
651 I103,
652 I104,
653 I105,
654 I106,
655 I107,
656 I108,
657 I109,
658 I110,
659 I111,
660 I112,
661 I113,
662 I114,
663 I115,
664 I116,
665 I117,
666 I118,
667 I119,
668 I120,
669 I121,
670 I122,
671 I123,
672 I124,
673 I125,
674 I126,
675 I127,
676 I128,
677 I129,
678 I130,
679 I131,
680 I132,
681 I133,
682 I134,
683 I135,
684 I136,
685 I137,
686 I138,
687 I139,
688 I140,
689 I141,
690 I142,
691 I143,
692 I144,
693 I145,
694 I146,
695 I147,
696 I148,
697 I149,
698 I150,
699 I151,
700 I152,
701 I153,
702 I154,
703 I155,
704 I156,
705 I157,
706 I158,
707 I159,
708 I160,
709 I161,
710 I162,
711 I163,
712 I164,
713 I165,
714 I166,
715 I167,
716 I168,
717 I169,
718 I170,
719 I171,
720 I172,
721 I173,
722 I174,
723 I175,
724 I176,
725 I177,
726 I178,
727 I179,
728 I180,
729 I181,
730 I182,
731 I183,
732 I184,
733 I185,
734 I186,
735 I187,
736 I188,
737 I189,
738 I190,
739 I191,
740 I192,
741 I193,
742 I194,
743 I195,
744 I196,
745 I197,
746 I198,
747 I199,
748 I200,
749 I201,
750 I202,
751 I203,
752 I204,
753 I205,
754 I206,
755 I207,
756 I208,
757 I209,
758 I210,
759 I211,
760 I212,
761 I213,
762 I214,
763 I215,
764 I216,
765 I217,
766 I218,
767 I219,
768 I220,
769 I221,
770 I222,
771 I223,
772 I224,
773 I225,
774 I226,
775 I227,
776 I228,
777 I229,
778 I230,
779 I231,
780 I232,
781 I233,
782 I234,
783 I235,
784 I236,
785 I237,
786 I238,
787 I239,
788 I240,
789 I241,
790 I242,
791 I243,
792 I244,
793 I245,
794 I246,
795 I247,
796 I248,
797 I249,
798 I250,
799 I251,
800 I252,
801 I253,
802 I254,
803 I255,
804 I256,
805};
806
807test "enum sizes" {
808 comptime {
809 try expect(@sizeOf(ValueCount1) == 0);
810 try expect(@sizeOf(ValueCount2) == 1);
811 try expect(@sizeOf(ValueCount256) == 1);
812 try expect(@sizeOf(ValueCount257) == 2);
813 }
814}
815
816const Small2 = enum(u2) {
817 One,
818 Two,
819};
820const Small = enum(u2) {
821 One,
822 Two,
823 Three,
824 Four,
825};
826
827test "set enum tag type" {
828 {
829 var x = Small.One;
830 x = Small.Two;
831 comptime try expect(Tag(Small) == u2);
832 }
833 {
834 var x = Small2.One;
835 x = Small2.Two;
836 comptime try expect(Tag(Small2) == u2);
837 }
838}
839
840const A = enum(u3) {
841 One,
842 Two,
843 Three,
844 Four,
845 One2,
846 Two2,
847 Three2,
848 Four2,
849};
850
851const B = enum(u3) {
852 One3,
853 Two3,
854 Three3,
855 Four3,
856 One23,
857 Two23,
858 Three23,
859 Four23,
860};
861
862const C = enum(u2) {
863 One4,
864 Two4,
865 Three4,
866 Four4,
867};
868
869const BitFieldOfEnums = packed struct {
870 a: A,
871 b: B,
872 c: C,
873};
874
875const bit_field_1 = BitFieldOfEnums{
876 .a = A.Two,
877 .b = B.Three3,
878 .c = C.Four4,
879};
880
881test "bit field access with enum fields" {
882 var data = bit_field_1;
883 try expect(getA(&data) == A.Two);
884 try expect(getB(&data) == B.Three3);
885 try expect(getC(&data) == C.Four4);
886 comptime try expect(@sizeOf(BitFieldOfEnums) == 1);
887
888 data.b = B.Four3;
889 try expect(data.b == B.Four3);
890
891 data.a = A.Three;
892 try expect(data.a == A.Three);
893 try expect(data.b == B.Four3);
894}
895
896fn getA(data: *const BitFieldOfEnums) A {
897 return data.a;
898}
899
900fn getB(data: *const BitFieldOfEnums) B {
901 return data.b;
902}
903
904fn getC(data: *const BitFieldOfEnums) C {
905 return data.c;
906}
907
908test "casting enum to its tag type" {
909 try testCastEnumTag(Small2.Two);
910 comptime try testCastEnumTag(Small2.Two);
911}
912
913fn testCastEnumTag(value: Small2) !void {
914 try expect(@enumToInt(value) == 1);
915}
916
917const MultipleChoice = enum(u32) {
918 A = 20,
919 B = 40,
920 C = 60,
921 D = 1000,
922};
923
924test "enum with specified tag values" {
925 try testEnumWithSpecifiedTagValues(MultipleChoice.C);
926 comptime try testEnumWithSpecifiedTagValues(MultipleChoice.C);
927}
928
929fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {
930 try expect(@enumToInt(x) == 60);
931 try expect(1234 == switch (x) {
932 MultipleChoice.A => 1,
933 MultipleChoice.B => 2,
934 MultipleChoice.C => @as(u32, 1234),
935 MultipleChoice.D => 4,
936 });
937}
938
939const MultipleChoice2 = enum(u32) {
940 Unspecified1,
941 A = 20,
942 Unspecified2,
943 B = 40,
944 Unspecified3,
945 C = 60,
946 Unspecified4,
947 D = 1000,
948 Unspecified5,
949};
950
951test "enum with specified and unspecified tag values" {
952 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
953 comptime try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
954}
955
956fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void {
957 try expect(@enumToInt(x) == 1000);
958 try expect(1234 == switch (x) {
959 MultipleChoice2.A => 1,
960 MultipleChoice2.B => 2,
961 MultipleChoice2.C => 3,
962 MultipleChoice2.D => @as(u32, 1234),
963 MultipleChoice2.Unspecified1 => 5,
964 MultipleChoice2.Unspecified2 => 6,
965 MultipleChoice2.Unspecified3 => 7,
966 MultipleChoice2.Unspecified4 => 8,
967 MultipleChoice2.Unspecified5 => 9,
968 });
969}
970
971test "cast integer literal to enum" {
972 try expect(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
973 try expect(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
974}
975
976const EnumWithOneMember = enum {
977 Eof,
978};
979
980fn doALoopThing(id: EnumWithOneMember) void {
981 while (true) {
982 if (id == EnumWithOneMember.Eof) {
983 break;
984 }
985 @compileError("above if condition should be comptime");
986 }
987}
988
989test "comparison operator on enum with one member is comptime known" {
990 doALoopThing(EnumWithOneMember.Eof);
991}
992
993const State = enum {
994 Start,
995};
996test "switch on enum with one member is comptime known" {
997 var state = State.Start;
998 switch (state) {
999 State.Start => return,
1000 }
1001 @compileError("analysis should not reach here");
1002}
1003
1004const EnumWithTagValues = enum(u4) {
1005 A = 1 << 0,
1006 B = 1 << 1,
1007 C = 1 << 2,
1008 D = 1 << 3,
1009};
1010test "enum with tag values don't require parens" {
1011 try expect(@enumToInt(EnumWithTagValues.C) == 0b0100);
1012}
1013
1014test "enum with 1 field but explicit tag type should still have the tag type" {
1015 const Enum = enum(u8) {
1016 B = 2,
1017 };
1018 comptime try expect(@sizeOf(Enum) == @sizeOf(u8));
1019}
1020
1021test "empty extern enum with members" {
1022 const E = extern enum {
1023 A,
1024 B,
1025 C,
1026 };
1027 try expect(@sizeOf(E) == @sizeOf(c_int));
1028}
1029
1030test "tag name with assigned enum values" {
1031 const LocalFoo = enum {
1032 A = 1,
1033 B = 0,
1034 };
1035 var b = LocalFoo.B;
1036 try expect(mem.eql(u8, @tagName(b), "B"));
1037}
1038
1039test "enum literal equality" {
1040 const x = .hi;
1041 const y = .ok;
1042 const z = .hi;
1043
1044 try expect(x != y);
1045 try expect(x == z);
1046}
1047
1048test "enum literal cast to enum" {
1049 const Color = enum {
1050 Auto,
1051 Off,
1052 On,
1053 };
1054
1055 var color1: Color = .Auto;
1056 var color2 = Color.Auto;
1057 try expect(color1 == color2);
1058}
1059
1060test "peer type resolution with enum literal" {
1061 const Items = enum {
1062 one,
1063 two,
1064 };
1065
1066 try expect(Items.two == .two);
1067 try expect(.two == Items.two);
1068}
1069
1070test "enum literal in array literal" {
1071 const Items = enum {
1072 one,
1073 two,
1074 };
1075
1076 const array = [_]Items{
1077 .one,
1078 .two,
1079 };
1080
1081 try expect(array[0] == .one);
1082 try expect(array[1] == .two);
1083}
1084
1085test "signed integer as enum tag" {
1086 const SignedEnum = enum(i2) {
1087 A0 = -1,
1088 A1 = 0,
1089 A2 = 1,
1090 };
1091
1092 try expect(@enumToInt(SignedEnum.A0) == -1);
1093 try expect(@enumToInt(SignedEnum.A1) == 0);
1094 try expect(@enumToInt(SignedEnum.A2) == 1);
1095}
1096
1097test "enum value allocation" {
1098 const LargeEnum = enum(u32) {
1099 A0 = 0x80000000,
1100 A1,
1101 A2,
1102 };
1103
1104 try expect(@enumToInt(LargeEnum.A0) == 0x80000000);
1105 try expect(@enumToInt(LargeEnum.A1) == 0x80000001);
1106 try expect(@enumToInt(LargeEnum.A2) == 0x80000002);
1107}
1108
1109test "enum literal casting to tagged union" {
1110 const Arch = union(enum) {
1111 x86_64,
1112 arm: Arm32,
1113
1114 const Arm32 = enum {
1115 v8_5a,
1116 v8_4a,
1117 };
1118 };
1119
1120 var t = true;
1121 var x: Arch = .x86_64;
1122 var y = if (t) x else .x86_64;
1123 switch (y) {
1124 .x86_64 => {},
1125 else => @panic("fail"),
1126 }
1127}
1128
1129test "enum with one member and custom tag type" {
1130 const E = enum(u2) {
1131 One,
1132 };
1133 try expect(@enumToInt(E.One) == 0);
1134 const E2 = enum(u2) {
1135 One = 2,
1136 };
1137 try expect(@enumToInt(E2.One) == 2);
1138}
1139
1140test "enum literal casting to optional" {
1141 var bar: ?Bar = undefined;
1142 bar = .B;
1143
1144 try expect(bar.? == Bar.B);
1145}
1146
1147test "enum literal casting to error union with payload enum" {
1148 var bar: error{B}!Bar = undefined;
1149 bar = .B; // should never cast to the error set
1150
1151 try expect((try bar) == Bar.B);
1152}
1153
1154test "enum with one member and u1 tag type @enumToInt" {
1155 const Enum = enum(u1) {
1156 Test,
1157 };
1158 try expect(@enumToInt(Enum.Test) == 0);
1159}
1160
1161test "enum with comptime_int tag type" {
1162 const Enum = enum(comptime_int) {
1163 One = 3,
1164 Two = 2,
1165 Three = 1,
1166 };
1167 comptime try expect(Tag(Enum) == comptime_int);
1168}
1169
1170test "enum with one member default to u0 tag type" {
1171 const E0 = enum {
1172 X,
1173 };
1174 comptime try expect(Tag(E0) == u0);
1175}
1176
1177test "tagName on enum literals" {
1178 try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
1179 comptime try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
1180}
1181
1182test "method call on an enum" {
1183 const S = struct {
1184 const E = enum {
1185 one,
1186 two,
1187
1188 fn method(self: *E) bool {
1189 return self.* == .two;
1190 }
1191
1192 fn generic_method(self: *E, foo: anytype) bool {
1193 return self.* == .two and foo == bool;
1194 }
1195 };
1196 fn doTheTest() !void {
1197 var e = E.two;
1198 try expect(e.method());
1199 try expect(e.generic_method(bool));
1200 }
1201 };
1202 try S.doTheTest();
1203 comptime try S.doTheTest();
1204}
test/stage1/behavior/enum_with_members.zig deleted-27
...@@ -1,27 +0,0 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3const fmt = @import("std").fmt;
4
5const ET = union(enum) {
6 SINT: i32,
7 UINT: u32,
8
9 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
10 return switch (a.*) {
11 ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}),
12 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}),
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 try expect((a.print(buf[0..]) catch unreachable) == 3);
23 try expect(mem.eql(u8, buf[0..3], "-42"));
24
25 try expect((b.print(buf[0..]) catch unreachable) == 2);
26 try expect(mem.eql(u8, buf[0..2], "42"));
27}
test/stage1/behavior/error.zig deleted-452
...@@ -1,452 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectError = std.testing.expectError;
4const expectEqual = std.testing.expectEqual;
5const mem = std.mem;
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 try expect((baz() catch unreachable) == 15);
23}
24
25fn gimmeItBroke() []const u8 {
26 return @errorName(error.ItBroke);
27}
28
29test "@errorName" {
30 try expect(mem.eql(u8, @errorName(error.AnError), "AnError"));
31 try expect(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
32}
33
34test "error values" {
35 const a = @errorToInt(error.err1);
36 const b = @errorToInt(error.err2);
37 try expect(a != b);
38}
39
40test "redefinition of error values allowed" {
41 shouldBeNotEqual(error.AnError, error.SecondError);
42}
43fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
44 if (a == b) unreachable;
45}
46
47test "error binary operator" {
48 const a = errBinaryOperatorG(true) catch 3;
49 const b = errBinaryOperatorG(false) catch 3;
50 try expect(a == 3);
51 try expect(b == 10);
52}
53fn errBinaryOperatorG(x: bool) anyerror!isize {
54 return if (x) error.ItBroke else @as(isize, 10);
55}
56
57test "unwrap simple value from error" {
58 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
59 try expect(i == 13);
60}
61fn unwrapSimpleValueFromErrorDo() anyerror!isize {
62 return 13;
63}
64
65test "error return in assignment" {
66 doErrReturnInAssignment() catch unreachable;
67}
68
69fn doErrReturnInAssignment() anyerror!void {
70 var x: i32 = undefined;
71 x = try makeANonErr();
72}
73
74fn makeANonErr() anyerror!i32 {
75 return 1;
76}
77
78test "error union type " {
79 try testErrorUnionType();
80 comptime try testErrorUnionType();
81}
82
83fn testErrorUnionType() !void {
84 const x: anyerror!i32 = 1234;
85 if (x) |value| try expect(value == 1234) else |_| unreachable;
86 try expect(@typeInfo(@TypeOf(x)) == .ErrorUnion);
87 try expect(@typeInfo(@typeInfo(@TypeOf(x)).ErrorUnion.error_set) == .ErrorSet);
88 try expect(@typeInfo(@TypeOf(x)).ErrorUnion.error_set == anyerror);
89}
90
91test "error set type" {
92 try testErrorSetType();
93 comptime try testErrorSetType();
94}
95
96const MyErrSet = error{
97 OutOfMemory,
98 FileNotFound,
99};
100
101fn testErrorSetType() !void {
102 try expect(@typeInfo(MyErrSet).ErrorSet.?.len == 2);
103
104 const a: MyErrSet!i32 = 5678;
105 const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
106
107 if (a) |value| try expect(value == 5678) else |err| switch (err) {
108 error.OutOfMemory => unreachable,
109 error.FileNotFound => unreachable,
110 }
111}
112
113test "explicit error set cast" {
114 try testExplicitErrorSetCast(Set1.A);
115 comptime try 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 try expect(y == error.A);
131}
132
133test "comptime test error for empty error set" {
134 try testComptimeTestErrorEmptySet(1234);
135 comptime try testComptimeTestErrorEmptySet(1234);
136}
137
138const EmptyErrorSet = error{};
139
140fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) !void {
141 if (x) |v| try expect(v == 1234) else |err| @compileError("bad");
142}
143
144test "syntax: optional operator in front of error union operator" {
145 comptime {
146 try expect(?(anyerror!i32) == ?(anyerror!i32));
147 }
148}
149
150test "comptime err to int of error set with only 1 possible value" {
151 testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
152 comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
153}
154fn testErrToIntWithOnePossibleValue(
155 x: error{A},
156 comptime value: u32,
157) void {
158 if (@errorToInt(x) != value) {
159 @compileError("bad");
160 }
161}
162
163test "empty error union" {
164 const x = error{} || error{};
165}
166
167test "error union peer type resolution" {
168 try testErrorUnionPeerTypeResolution(1);
169}
170
171fn testErrorUnionPeerTypeResolution(x: i32) !void {
172 const y = switch (x) {
173 1 => bar_1(),
174 2 => baz_1(),
175 else => quux_1(),
176 };
177 if (y) |_| {
178 @panic("expected error");
179 } else |e| {
180 try expect(e == error.A);
181 }
182}
183
184fn bar_1() anyerror {
185 return error.A;
186}
187
188fn baz_1() !i32 {
189 return error.B;
190}
191
192fn quux_1() !i32 {
193 return error.C;
194}
195
196test "error: fn returning empty error set can be passed as fn returning any error" {
197 entry();
198 comptime entry();
199}
200
201fn entry() void {
202 foo2(bar2);
203}
204
205fn foo2(f: fn () anyerror!void) void {
206 const x = f();
207}
208
209fn bar2() (error{}!void) {}
210
211test "error: Zero sized error set returned with value payload crash" {
212 _ = foo3(0) catch {};
213 _ = comptime foo3(0) catch {};
214}
215
216const Error = error{};
217fn foo3(b: usize) Error!usize {
218 return b;
219}
220
221test "error: Infer error set from literals" {
222 _ = nullLiteral("n") catch |err| handleErrors(err);
223 _ = floatLiteral("n") catch |err| handleErrors(err);
224 _ = intLiteral("n") catch |err| handleErrors(err);
225 _ = comptime nullLiteral("n") catch |err| handleErrors(err);
226 _ = comptime floatLiteral("n") catch |err| handleErrors(err);
227 _ = comptime intLiteral("n") catch |err| handleErrors(err);
228}
229
230fn handleErrors(err: anytype) noreturn {
231 switch (err) {
232 error.T => {},
233 }
234
235 unreachable;
236}
237
238fn nullLiteral(str: []const u8) !?i64 {
239 if (str[0] == 'n') return null;
240
241 return error.T;
242}
243
244fn floatLiteral(str: []const u8) !?f64 {
245 if (str[0] == 'n') return 1.0;
246
247 return error.T;
248}
249
250fn intLiteral(str: []const u8) !?i64 {
251 if (str[0] == 'n') return 1;
252
253 return error.T;
254}
255
256test "nested error union function call in optional unwrap" {
257 const S = struct {
258 const Foo = struct {
259 a: i32,
260 };
261
262 fn errorable() !i32 {
263 var x: Foo = (try getFoo()) orelse return error.Other;
264 return x.a;
265 }
266
267 fn errorable2() !i32 {
268 var x: Foo = (try getFoo2()) orelse return error.Other;
269 return x.a;
270 }
271
272 fn errorable3() !i32 {
273 var x: Foo = (try getFoo3()) orelse return error.Other;
274 return x.a;
275 }
276
277 fn getFoo() anyerror!?Foo {
278 return Foo{ .a = 1234 };
279 }
280
281 fn getFoo2() anyerror!?Foo {
282 return error.Failure;
283 }
284
285 fn getFoo3() anyerror!?Foo {
286 return null;
287 }
288 };
289 try expect((try S.errorable()) == 1234);
290 try expectError(error.Failure, S.errorable2());
291 try expectError(error.Other, S.errorable3());
292 comptime {
293 try expect((try S.errorable()) == 1234);
294 try expectError(error.Failure, S.errorable2());
295 try expectError(error.Other, S.errorable3());
296 }
297}
298
299test "widen cast integer payload of error union function call" {
300 const S = struct {
301 fn errorable() !u64 {
302 var x = @as(u64, try number());
303 return x;
304 }
305
306 fn number() anyerror!u32 {
307 return 1234;
308 }
309 };
310 try expect((try S.errorable()) == 1234);
311}
312
313test "return function call to error set from error union function" {
314 const S = struct {
315 fn errorable() anyerror!i32 {
316 return fail();
317 }
318
319 fn fail() anyerror {
320 return error.Failure;
321 }
322 };
323 try expectError(error.Failure, S.errorable());
324 comptime try expectError(error.Failure, S.errorable());
325}
326
327test "optional error set is the same size as error set" {
328 comptime try expect(@sizeOf(?anyerror) == @sizeOf(anyerror));
329 const S = struct {
330 fn returnsOptErrSet() ?anyerror {
331 return null;
332 }
333 };
334 try expect(S.returnsOptErrSet() == null);
335 comptime try expect(S.returnsOptErrSet() == null);
336}
337
338test "debug info for optional error set" {
339 const SomeError = error{Hello};
340 var a_local_variable: ?SomeError = null;
341}
342
343test "nested catch" {
344 const S = struct {
345 fn entry() !void {
346 try expectError(error.Bad, func());
347 }
348 fn fail() anyerror!Foo {
349 return error.Wrong;
350 }
351 fn func() anyerror!Foo {
352 const x = fail() catch
353 fail() catch
354 return error.Bad;
355 unreachable;
356 }
357 const Foo = struct {
358 field: i32,
359 };
360 };
361 try S.entry();
362 comptime try S.entry();
363}
364
365test "implicit cast to optional to error union to return result loc" {
366 const S = struct {
367 fn entry() !void {
368 var x: Foo = undefined;
369 if (func(&x)) |opt| {
370 try expect(opt != null);
371 } else |_| @panic("expected non error");
372 }
373 fn func(f: *Foo) anyerror!?*Foo {
374 return f;
375 }
376 const Foo = struct {
377 field: i32,
378 };
379 };
380 try S.entry();
381 //comptime S.entry(); TODO
382}
383
384test "function pointer with return type that is error union with payload which is pointer of parent struct" {
385 const S = struct {
386 const Foo = struct {
387 fun: fn (a: i32) (anyerror!*Foo),
388 };
389
390 const Err = error{UnspecifiedErr};
391
392 fn bar(a: i32) anyerror!*Foo {
393 return Err.UnspecifiedErr;
394 }
395
396 fn doTheTest() !void {
397 var x = Foo{ .fun = bar };
398 try expectError(error.UnspecifiedErr, x.fun(1));
399 }
400 };
401 try S.doTheTest();
402}
403
404test "return result loc as peer result loc in inferred error set function" {
405 const S = struct {
406 fn doTheTest() !void {
407 if (foo(2)) |x| {
408 try expect(x.Two);
409 } else |e| switch (e) {
410 error.Whatever => @panic("fail"),
411 }
412 try expectError(error.Whatever, foo(99));
413 }
414 const FormValue = union(enum) {
415 One: void,
416 Two: bool,
417 };
418
419 fn foo(id: u64) !FormValue {
420 return switch (id) {
421 2 => FormValue{ .Two = true },
422 1 => FormValue{ .One = {} },
423 else => return error.Whatever,
424 };
425 }
426 };
427 try S.doTheTest();
428 comptime try S.doTheTest();
429}
430
431test "error payload type is correctly resolved" {
432 const MyIntWrapper = struct {
433 const Self = @This();
434
435 x: i32,
436
437 pub fn create() anyerror!Self {
438 return Self{ .x = 42 };
439 }
440 };
441
442 try expectEqual(MyIntWrapper{ .x = 42 }, try MyIntWrapper.create());
443}
444
445test "error union comptime caching" {
446 const S = struct {
447 fn foo(comptime arg: anytype) void {}
448 };
449
450 S.foo(@as(anyerror!void, {}));
451 S.foo(@as(anyerror!void, {}));
452}
test/stage1/behavior/eval.zig deleted-833
...@@ -1,833 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const builtin = @import("builtin");
5
6test "compile time recursion" {
7 try expect(some_data.len == 21);
8}
9var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined;
10fn fibonacci(x: i32) i32 {
11 if (x <= 1) return 1;
12 return fibonacci(x - 1) + fibonacci(x - 2);
13}
14
15fn unwrapAndAddOne(blah: ?i32) i32 {
16 return blah.? + 1;
17}
18const should_be_1235 = unwrapAndAddOne(1234);
19test "static add one" {
20 try expect(should_be_1235 == 1235);
21}
22
23test "inlined loop" {
24 comptime var i = 0;
25 comptime var sum = 0;
26 inline while (i <= 5) : (i += 1)
27 sum += i;
28 try expect(sum == 15);
29}
30
31fn gimme1or2(comptime a: bool) i32 {
32 const x: i32 = 1;
33 const y: i32 = 2;
34 comptime var z: i32 = if (a) x else y;
35 return z;
36}
37test "inline variable gets result of const if" {
38 try expect(gimme1or2(true) == 1);
39 try expect(gimme1or2(false) == 2);
40}
41
42test "static function evaluation" {
43 try expect(statically_added_number == 3);
44}
45const statically_added_number = staticAdd(1, 2);
46fn staticAdd(a: i32, b: i32) i32 {
47 return a + b;
48}
49
50test "const expr eval on single expr blocks" {
51 try expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
52 comptime try expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
53}
54
55fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
56 const literal = 3;
57
58 const result = if (b) b: {
59 break :b literal;
60 } else b: {
61 break :b x;
62 };
63
64 return result;
65}
66
67test "statically initialized list" {
68 try expect(static_point_list[0].x == 1);
69 try expect(static_point_list[0].y == 2);
70 try expect(static_point_list[1].x == 3);
71 try expect(static_point_list[1].y == 4);
72}
73const Point = struct {
74 x: i32,
75 y: i32,
76};
77const static_point_list = [_]Point{
78 makePoint(1, 2),
79 makePoint(3, 4),
80};
81fn makePoint(x: i32, y: i32) Point {
82 return Point{
83 .x = x,
84 .y = y,
85 };
86}
87
88test "static eval list init" {
89 try expect(static_vec3.data[2] == 1.0);
90 try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
91}
92const static_vec3 = vec3(0.0, 0.0, 1.0);
93pub const Vec3 = struct {
94 data: [3]f32,
95};
96pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
97 return Vec3{
98 .data = [_]f32{
99 x,
100 y,
101 z,
102 },
103 };
104}
105
106test "constant expressions" {
107 var array: [array_size]u8 = undefined;
108 try expect(@sizeOf(@TypeOf(array)) == 20);
109}
110const array_size: u8 = 20;
111
112test "constant struct with negation" {
113 try expect(vertices[0].x == -0.6);
114}
115const Vertex = struct {
116 x: f32,
117 y: f32,
118 r: f32,
119 g: f32,
120 b: f32,
121};
122const vertices = [_]Vertex{
123 Vertex{
124 .x = -0.6,
125 .y = -0.4,
126 .r = 1.0,
127 .g = 0.0,
128 .b = 0.0,
129 },
130 Vertex{
131 .x = 0.6,
132 .y = -0.4,
133 .r = 0.0,
134 .g = 1.0,
135 .b = 0.0,
136 },
137 Vertex{
138 .x = 0.0,
139 .y = 0.6,
140 .r = 0.0,
141 .g = 0.0,
142 .b = 1.0,
143 },
144};
145
146test "statically initialized struct" {
147 st_init_str_foo.x += 1;
148 try expect(st_init_str_foo.x == 14);
149}
150const StInitStrFoo = struct {
151 x: i32,
152 y: bool,
153};
154var st_init_str_foo = StInitStrFoo{
155 .x = 13,
156 .y = true,
157};
158
159test "statically initalized array literal" {
160 const y: [4]u8 = st_init_arr_lit_x;
161 try expect(y[3] == 4);
162}
163const st_init_arr_lit_x = [_]u8{
164 1,
165 2,
166 3,
167 4,
168};
169
170test "const slice" {
171 comptime {
172 const a = "1234567890";
173 try expect(a.len == 10);
174 const b = a[1..2];
175 try expect(b.len == 1);
176 try expect(b[0] == '2');
177 }
178}
179
180test "try to trick eval with runtime if" {
181 try expect(testTryToTrickEvalWithRuntimeIf(true) == 10);
182}
183
184fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
185 comptime var i: usize = 0;
186 inline while (i < 10) : (i += 1) {
187 const result = if (b) false else true;
188 }
189 comptime {
190 return i;
191 }
192}
193
194test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
195 var runtime = [1]i32{3};
196 comptime var i: usize = 0;
197 inline while (i < 2) : (i += 1) {
198 const result = if (i == 0) [1]i32{2} else runtime;
199 }
200 comptime {
201 try expect(i == 2);
202 }
203}
204
205fn max(comptime T: type, a: T, b: T) T {
206 if (T == bool) {
207 return a or b;
208 } else if (a > b) {
209 return a;
210 } else {
211 return b;
212 }
213}
214fn letsTryToCompareBools(a: bool, b: bool) bool {
215 return max(bool, a, b);
216}
217test "inlined block and runtime block phi" {
218 try expect(letsTryToCompareBools(true, true));
219 try expect(letsTryToCompareBools(true, false));
220 try expect(letsTryToCompareBools(false, true));
221 try expect(!letsTryToCompareBools(false, false));
222
223 comptime {
224 try expect(letsTryToCompareBools(true, true));
225 try expect(letsTryToCompareBools(true, false));
226 try expect(letsTryToCompareBools(false, true));
227 try expect(!letsTryToCompareBools(false, false));
228 }
229}
230
231const CmdFn = struct {
232 name: []const u8,
233 func: fn (i32) i32,
234};
235
236const cmd_fns = [_]CmdFn{
237 CmdFn{
238 .name = "one",
239 .func = one,
240 },
241 CmdFn{
242 .name = "two",
243 .func = two,
244 },
245 CmdFn{
246 .name = "three",
247 .func = three,
248 },
249};
250fn one(value: i32) i32 {
251 return value + 1;
252}
253fn two(value: i32) i32 {
254 return value + 2;
255}
256fn three(value: i32) i32 {
257 return value + 3;
258}
259
260fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
261 var result: i32 = start_value;
262 comptime var i = 0;
263 inline while (i < cmd_fns.len) : (i += 1) {
264 if (cmd_fns[i].name[0] == prefix_char) {
265 result = cmd_fns[i].func(result);
266 }
267 }
268 return result;
269}
270
271test "comptime iterate over fn ptr list" {
272 try expect(performFn('t', 1) == 6);
273 try expect(performFn('o', 0) == 1);
274 try expect(performFn('w', 99) == 99);
275}
276
277test "eval @setRuntimeSafety at compile-time" {
278 const result = comptime fnWithSetRuntimeSafety();
279 try expect(result == 1234);
280}
281
282fn fnWithSetRuntimeSafety() i32 {
283 @setRuntimeSafety(true);
284 return 1234;
285}
286
287test "eval @setFloatMode at compile-time" {
288 const result = comptime fnWithFloatMode();
289 try expect(result == 1234.0);
290}
291
292fn fnWithFloatMode() f32 {
293 @setFloatMode(builtin.FloatMode.Strict);
294 return 1234.0;
295}
296
297const SimpleStruct = struct {
298 field: i32,
299
300 fn method(self: *const SimpleStruct) i32 {
301 return self.field + 3;
302 }
303};
304
305var simple_struct = SimpleStruct{ .field = 1234 };
306
307const bound_fn = simple_struct.method;
308
309test "call method on bound fn referring to var instance" {
310 try expect(bound_fn() == 1237);
311}
312
313test "ptr to local array argument at comptime" {
314 comptime {
315 var bytes: [10]u8 = undefined;
316 modifySomeBytes(bytes[0..]);
317 try expect(bytes[0] == 'a');
318 try expect(bytes[9] == 'b');
319 }
320}
321
322fn modifySomeBytes(bytes: []u8) void {
323 bytes[0] = 'a';
324 bytes[9] = 'b';
325}
326
327test "comparisons 0 <= uint and 0 > uint should be comptime" {
328 testCompTimeUIntComparisons(1234);
329}
330fn testCompTimeUIntComparisons(x: u32) void {
331 if (!(0 <= x)) {
332 @compileError("this condition should be comptime known");
333 }
334 if (0 > x) {
335 @compileError("this condition should be comptime known");
336 }
337 if (!(x >= 0)) {
338 @compileError("this condition should be comptime known");
339 }
340 if (x < 0) {
341 @compileError("this condition should be comptime known");
342 }
343}
344
345test "const ptr to variable data changes at runtime" {
346 try expect(foo_ref.name[0] == 'a');
347 foo_ref.name = "b";
348 try expect(foo_ref.name[0] == 'b');
349}
350
351const Foo = struct {
352 name: []const u8,
353};
354
355var foo_contents = Foo{ .name = "a" };
356const foo_ref = &foo_contents;
357
358test "create global array with for loop" {
359 try expect(global_array[5] == 5 * 5);
360 try expect(global_array[9] == 9 * 9);
361}
362
363const global_array = x: {
364 var result: [10]usize = undefined;
365 for (result) |*item, index| {
366 item.* = index * index;
367 }
368 break :x result;
369};
370
371test "compile-time downcast when the bits fit" {
372 comptime {
373 const spartan_count: u16 = 255;
374 const byte = @intCast(u8, spartan_count);
375 try expect(byte == 255);
376 }
377}
378
379const hi1 = "hi";
380const hi2 = hi1;
381test "const global shares pointer with other same one" {
382 try assertEqualPtrs(&hi1[0], &hi2[0]);
383 comptime try expect(&hi1[0] == &hi2[0]);
384}
385fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void {
386 try expect(ptr1 == ptr2);
387}
388
389test "@setEvalBranchQuota" {
390 comptime {
391 // 1001 for the loop and then 1 more for the expect fn call
392 @setEvalBranchQuota(1002);
393 var i = 0;
394 var sum = 0;
395 while (i < 1001) : (i += 1) {
396 sum += i;
397 }
398 try expect(sum == 500500);
399 }
400}
401
402test "float literal at compile time not lossy" {
403 try expect(16777216.0 + 1.0 == 16777217.0);
404 try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
405}
406
407test "f32 at compile time is lossy" {
408 try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
409}
410
411test "f64 at compile time is lossy" {
412 try expect(@as(f64, 1 << 53) + 1 == 1 << 53);
413}
414
415test "f128 at compile time is lossy" {
416 try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
417}
418
419comptime {
420 try expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192);
421}
422
423pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
424 return struct {
425 pub const Node = struct {};
426 };
427}
428
429test "string literal used as comptime slice is memoized" {
430 const a = "link";
431 const b = "link";
432 comptime try expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
433 comptime try expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
434}
435
436test "comptime slice of undefined pointer of length 0" {
437 const slice1 = @as([*]i32, undefined)[0..0];
438 try expect(slice1.len == 0);
439 const slice2 = @as([*]i32, undefined)[100..100];
440 try expect(slice2.len == 0);
441}
442
443fn copyWithPartialInline(s: []u32, b: []u8) void {
444 comptime var i: usize = 0;
445 inline while (i < 4) : (i += 1) {
446 s[i] = 0;
447 s[i] |= @as(u32, b[i * 4 + 0]) << 24;
448 s[i] |= @as(u32, b[i * 4 + 1]) << 16;
449 s[i] |= @as(u32, b[i * 4 + 2]) << 8;
450 s[i] |= @as(u32, b[i * 4 + 3]) << 0;
451 }
452}
453
454test "binary math operator in partially inlined function" {
455 var s: [4]u32 = undefined;
456 var b: [16]u8 = undefined;
457
458 for (b) |*r, i|
459 r.* = @intCast(u8, i + 1);
460
461 copyWithPartialInline(s[0..], b[0..]);
462 try expect(s[0] == 0x1020304);
463 try expect(s[1] == 0x5060708);
464 try expect(s[2] == 0x90a0b0c);
465 try expect(s[3] == 0xd0e0f10);
466}
467
468test "comptime function with the same args is memoized" {
469 comptime {
470 try expect(MakeType(i32) == MakeType(i32));
471 try expect(MakeType(i32) != MakeType(f64));
472 }
473}
474
475fn MakeType(comptime T: type) type {
476 return struct {
477 field: T,
478 };
479}
480
481test "comptime function with mutable pointer is not memoized" {
482 comptime {
483 var x: i32 = 1;
484 const ptr = &x;
485 increment(ptr);
486 increment(ptr);
487 try expect(x == 3);
488 }
489}
490
491fn increment(value: *i32) void {
492 value.* += 1;
493}
494
495fn generateTable(comptime T: type) [1010]T {
496 var res: [1010]T = undefined;
497 var i: usize = 0;
498 while (i < 1010) : (i += 1) {
499 res[i] = @intCast(T, i);
500 }
501 return res;
502}
503
504fn doesAlotT(comptime T: type, value: usize) T {
505 @setEvalBranchQuota(5000);
506 const table = comptime blk: {
507 break :blk generateTable(T);
508 };
509 return table[value];
510}
511
512test "@setEvalBranchQuota at same scope as generic function call" {
513 try expect(doesAlotT(u32, 2) == 2);
514}
515
516test "comptime slice of slice preserves comptime var" {
517 comptime {
518 var buff: [10]u8 = undefined;
519 buff[0..][0..][0] = 1;
520 try expect(buff[0..][0..][0] == 1);
521 }
522}
523
524test "comptime slice of pointer preserves comptime var" {
525 comptime {
526 var buff: [10]u8 = undefined;
527 var a = @ptrCast([*]u8, &buff);
528 a[0..1][0] = 1;
529 try expect(buff[0..][0..][0] == 1);
530 }
531}
532
533const SingleFieldStruct = struct {
534 x: i32,
535
536 fn read_x(self: *const SingleFieldStruct) i32 {
537 return self.x;
538 }
539};
540test "const ptr to comptime mutable data is not memoized" {
541 comptime {
542 var foo = SingleFieldStruct{ .x = 1 };
543 try expect(foo.read_x() == 1);
544 foo.x = 2;
545 try expect(foo.read_x() == 2);
546 }
547}
548
549test "array concat of slices gives slice" {
550 comptime {
551 var a: []const u8 = "aoeu";
552 var b: []const u8 = "asdf";
553 const c = a ++ b;
554 try expect(std.mem.eql(u8, c, "aoeuasdf"));
555 }
556}
557
558test "comptime shlWithOverflow" {
559 const ct_shifted: u64 = comptime amt: {
560 var amt = @as(u64, 0);
561 _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
562 break :amt amt;
563 };
564
565 const rt_shifted: u64 = amt: {
566 var amt = @as(u64, 0);
567 _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
568 break :amt amt;
569 };
570
571 try expect(ct_shifted == rt_shifted);
572}
573
574test "runtime 128 bit integer division" {
575 var a: u128 = 152313999999999991610955792383;
576 var b: u128 = 10000000000000000000;
577 var c = a / b;
578 try expect(c == 15231399999);
579}
580
581pub const Info = struct {
582 version: u8,
583};
584
585pub const diamond_info = Info{ .version = 0 };
586
587test "comptime modification of const struct field" {
588 comptime {
589 var res = diamond_info;
590 res.version = 1;
591 try expect(diamond_info.version == 0);
592 try expect(res.version == 1);
593 }
594}
595
596test "pointer to type" {
597 comptime {
598 var T: type = i32;
599 try expect(T == i32);
600 var ptr = &T;
601 try expect(@TypeOf(ptr) == *type);
602 ptr.* = f32;
603 try expect(T == f32);
604 try expect(*T == *f32);
605 }
606}
607
608test "slice of type" {
609 comptime {
610 var types_array = [_]type{ i32, f64, type };
611 for (types_array) |T, i| {
612 switch (i) {
613 0 => try expect(T == i32),
614 1 => try expect(T == f64),
615 2 => try expect(T == type),
616 else => unreachable,
617 }
618 }
619 for (types_array[0..]) |T, i| {
620 switch (i) {
621 0 => try expect(T == i32),
622 1 => try expect(T == f64),
623 2 => try expect(T == type),
624 else => unreachable,
625 }
626 }
627 }
628}
629
630const Wrapper = struct {
631 T: type,
632};
633
634fn wrap(comptime T: type) Wrapper {
635 return Wrapper{ .T = T };
636}
637
638test "function which returns struct with type field causes implicit comptime" {
639 const ty = wrap(i32).T;
640 try expect(ty == i32);
641}
642
643test "call method with comptime pass-by-non-copying-value self parameter" {
644 const S = struct {
645 a: u8,
646
647 fn b(comptime s: @This()) u8 {
648 return s.a;
649 }
650 };
651
652 const s = S{ .a = 2 };
653 var b = s.b();
654 try expect(b == 2);
655}
656
657test "@tagName of @typeInfo" {
658 const str = @tagName(@typeInfo(u8));
659 try expect(std.mem.eql(u8, str, "Int"));
660}
661
662test "setting backward branch quota just before a generic fn call" {
663 @setEvalBranchQuota(1001);
664 loopNTimes(1001);
665}
666
667fn loopNTimes(comptime n: usize) void {
668 comptime var i = 0;
669 inline while (i < n) : (i += 1) {}
670}
671
672test "variable inside inline loop that has different types on different iterations" {
673 try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
674}
675
676fn testVarInsideInlineLoop(args: anytype) !void {
677 comptime var i = 0;
678 inline while (i < args.len) : (i += 1) {
679 const x = args[i];
680 if (i == 0) try expect(x);
681 if (i == 1) try expect(x == 42);
682 }
683}
684
685test "inline for with same type but different values" {
686 var res: usize = 0;
687 inline for ([_]type{ [2]u8, [1]u8, [2]u8 }) |T| {
688 var a: T = undefined;
689 res += a.len;
690 }
691 try expect(res == 5);
692}
693
694test "refer to the type of a generic function" {
695 const Func = fn (type) void;
696 const f: Func = doNothingWithType;
697 f(i32);
698}
699
700fn doNothingWithType(comptime T: type) void {}
701
702test "zero extend from u0 to u1" {
703 var zero_u0: u0 = 0;
704 var zero_u1: u1 = zero_u0;
705 try expect(zero_u1 == 0);
706}
707
708test "bit shift a u1" {
709 var x: u1 = 1;
710 var y = x << 0;
711 try expect(y == 1);
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 try expect(sliceA[1] == 2);
724 try expect(sliceB[1] == 2);
725}
726
727test "slice bounds in comptime concatenation" {
728 const bs = comptime blk: {
729 const b = "........1........";
730 break :blk b[8..9];
731 };
732 const str = "" ++ bs;
733 try expect(str.len == 1);
734 try expect(std.mem.eql(u8, str, "1"));
735
736 const str2 = bs ++ "";
737 try expect(str2.len == 1);
738 try expect(std.mem.eql(u8, str2, "1"));
739}
740
741test "comptime bitwise operators" {
742 comptime {
743 try expect(3 & 1 == 1);
744 try expect(3 & -1 == 3);
745 try expect(-3 & -1 == -3);
746 try expect(3 | -1 == -1);
747 try expect(-3 | -1 == -1);
748 try expect(3 ^ -1 == -4);
749 try expect(-3 ^ -1 == 2);
750 try expect(~@as(i8, -1) == 0);
751 try expect(~@as(i128, -1) == 0);
752 try expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
753 try expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
754 try expect(~@as(u128, 0) == 0xffffffffffffffffffffffffffffffff);
755 }
756}
757
758test "*align(1) u16 is the same as *align(1:0:2) u16" {
759 comptime {
760 try expect(*align(1:0:2) u16 == *align(1) u16);
761 try expect(*align(2:0:2) u16 == *u16);
762 }
763}
764
765test "array concatenation forces comptime" {
766 var a = oneItem(3) ++ oneItem(4);
767 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
768}
769
770test "array multiplication forces comptime" {
771 var a = oneItem(3) ** scalar(2);
772 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
773}
774
775fn oneItem(x: i32) [1]i32 {
776 return [_]i32{x};
777}
778
779fn scalar(x: u32) u32 {
780 return x;
781}
782
783test "no undeclared identifier error in unanalyzed branches" {
784 if (false) {
785 lol_this_doesnt_exist = nonsense;
786 }
787}
788
789test "comptime assign int to optional int" {
790 comptime {
791 var x: ?i32 = null;
792 x = 2;
793 x.? *= 10;
794 try expectEqual(20, x.?);
795 }
796}
797
798test "return 0 from function that has u0 return type" {
799 const S = struct {
800 fn foo_zero() u0 {
801 return 0;
802 }
803 };
804 comptime {
805 if (S.foo_zero() != 0) {
806 @compileError("test failed");
807 }
808 }
809}
810
811test "two comptime calls with array default initialized to undefined" {
812 const S = struct {
813 const CrossTarget = struct {
814 dynamic_linker: DynamicLinker = DynamicLinker{},
815
816 pub fn parse() void {
817 var result: CrossTarget = .{};
818 result.getCpuArch();
819 }
820
821 pub fn getCpuArch(self: CrossTarget) void {}
822 };
823
824 const DynamicLinker = struct {
825 buffer: [255]u8 = undefined,
826 };
827 };
828
829 comptime {
830 S.CrossTarget.parse();
831 S.CrossTarget.parse();
832 }
833}
test/stage1/behavior/field_parent_ptr.zig deleted-41
...@@ -1,41 +0,0 @@
1const expect = @import("std").testing.expect;
2
3test "@fieldParentPtr non-first field" {
4 try testParentFieldPtr(&foo.c);
5 comptime try testParentFieldPtr(&foo.c);
6}
7
8test "@fieldParentPtr first field" {
9 try testParentFieldPtrFirst(&foo.a);
10 comptime try 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 try expect(c == &foo.c);
29
30 const base = @fieldParentPtr(Foo, "c", c);
31 try expect(base == &foo);
32 try expect(&base.c == c);
33}
34
35fn testParentFieldPtrFirst(a: *const bool) !void {
36 try expect(a == &foo.a);
37
38 const base = @fieldParentPtr(Foo, "a", a);
39 try expect(base == &foo);
40 try expect(&base.a == a);
41}
test/stage1/behavior/floatop.zig deleted-465
...@@ -1,465 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const math = std.math;
4const pi = std.math.pi;
5const e = std.math.e;
6const Vector = std.meta.Vector;
7
8const epsilon = 0.000001;
9
10test "@sqrt" {
11 comptime try testSqrt();
12 try testSqrt();
13}
14
15fn testSqrt() !void {
16 {
17 var a: f16 = 4;
18 try expect(@sqrt(a) == 2);
19 }
20 {
21 var a: f32 = 9;
22 try expect(@sqrt(a) == 3);
23 var b: f32 = 1.1;
24 try expect(math.approxEqAbs(f32, @sqrt(b), 1.0488088481701516, epsilon));
25 }
26 {
27 var a: f64 = 25;
28 try expect(@sqrt(a) == 5);
29 }
30 {
31 const a: comptime_float = 25.0;
32 try expect(@sqrt(a) == 5.0);
33 }
34 // TODO https://github.com/ziglang/zig/issues/4026
35 //{
36 // var a: f128 = 49;
37 //try expect(@sqrt(a) == 7);
38 //}
39 {
40 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
41 var result = @sqrt(v);
42 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon));
43 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon));
44 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 3.3)), result[2], epsilon));
45 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon));
46 }
47}
48
49test "more @sqrt f16 tests" {
50 // TODO these are not all passing at comptime
51 try expect(@sqrt(@as(f16, 0.0)) == 0.0);
52 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 2.0)), 1.414214, epsilon));
53 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 3.6)), 1.897367, epsilon));
54 try expect(@sqrt(@as(f16, 4.0)) == 2.0);
55 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 7.539840)), 2.745877, epsilon));
56 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 19.230934)), 4.385309, epsilon));
57 try expect(@sqrt(@as(f16, 64.0)) == 8.0);
58 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 64.1)), 8.006248, epsilon));
59 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 8942.230469)), 94.563370, epsilon));
60
61 // special cases
62 try expect(math.isPositiveInf(@sqrt(@as(f16, math.inf(f16)))));
63 try expect(@sqrt(@as(f16, 0.0)) == 0.0);
64 try expect(@sqrt(@as(f16, -0.0)) == -0.0);
65 try expect(math.isNan(@sqrt(@as(f16, -1.0))));
66 try expect(math.isNan(@sqrt(@as(f16, math.nan(f16)))));
67}
68
69test "@sin" {
70 comptime try testSin();
71 try testSin();
72}
73
74fn testSin() !void {
75 // TODO test f128, and c_longdouble
76 // https://github.com/ziglang/zig/issues/4026
77 {
78 var a: f16 = 0;
79 try expect(@sin(a) == 0);
80 }
81 {
82 var a: f32 = 0;
83 try expect(@sin(a) == 0);
84 }
85 {
86 var a: f64 = 0;
87 try expect(@sin(a) == 0);
88 }
89 {
90 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
91 var result = @sin(v);
92 try expect(math.approxEqAbs(f32, @sin(@as(f32, 1.1)), result[0], epsilon));
93 try expect(math.approxEqAbs(f32, @sin(@as(f32, 2.2)), result[1], epsilon));
94 try expect(math.approxEqAbs(f32, @sin(@as(f32, 3.3)), result[2], epsilon));
95 try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon));
96 }
97}
98
99test "@cos" {
100 comptime try testCos();
101 try testCos();
102}
103
104fn testCos() !void {
105 // TODO test f128, and c_longdouble
106 // https://github.com/ziglang/zig/issues/4026
107 {
108 var a: f16 = 0;
109 try expect(@cos(a) == 1);
110 }
111 {
112 var a: f32 = 0;
113 try expect(@cos(a) == 1);
114 }
115 {
116 var a: f64 = 0;
117 try expect(@cos(a) == 1);
118 }
119 {
120 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
121 var result = @cos(v);
122 try expect(math.approxEqAbs(f32, @cos(@as(f32, 1.1)), result[0], epsilon));
123 try expect(math.approxEqAbs(f32, @cos(@as(f32, 2.2)), result[1], epsilon));
124 try expect(math.approxEqAbs(f32, @cos(@as(f32, 3.3)), result[2], epsilon));
125 try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon));
126 }
127}
128
129test "@exp" {
130 comptime try testExp();
131 try testExp();
132}
133
134fn testExp() !void {
135 // TODO test f128, and c_longdouble
136 // https://github.com/ziglang/zig/issues/4026
137 {
138 var a: f16 = 0;
139 try expect(@exp(a) == 1);
140 }
141 {
142 var a: f32 = 0;
143 try expect(@exp(a) == 1);
144 }
145 {
146 var a: f64 = 0;
147 try expect(@exp(a) == 1);
148 }
149 {
150 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
151 var result = @exp(v);
152 try expect(math.approxEqAbs(f32, @exp(@as(f32, 1.1)), result[0], epsilon));
153 try expect(math.approxEqAbs(f32, @exp(@as(f32, 2.2)), result[1], epsilon));
154 try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.3)), result[2], epsilon));
155 try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.4)), result[3], epsilon));
156 }
157}
158
159test "@exp2" {
160 comptime try testExp2();
161 try testExp2();
162}
163
164fn testExp2() !void {
165 // TODO test f128, and c_longdouble
166 // https://github.com/ziglang/zig/issues/4026
167 {
168 var a: f16 = 2;
169 try expect(@exp2(a) == 4);
170 }
171 {
172 var a: f32 = 2;
173 try expect(@exp2(a) == 4);
174 }
175 {
176 var a: f64 = 2;
177 try expect(@exp2(a) == 4);
178 }
179 {
180 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
181 var result = @exp2(v);
182 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 1.1)), result[0], epsilon));
183 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 2.2)), result[1], epsilon));
184 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.3)), result[2], epsilon));
185 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.4)), result[3], epsilon));
186 }
187}
188
189test "@log" {
190 // Old musl (and glibc?), and our current math.ln implementation do not return 1
191 // so also accept those values.
192 comptime try testLog();
193 try testLog();
194}
195
196fn testLog() !void {
197 // TODO test f128, and c_longdouble
198 // https://github.com/ziglang/zig/issues/4026
199 {
200 var a: f16 = e;
201 try expect(math.approxEqAbs(f16, @log(a), 1, epsilon));
202 }
203 {
204 var a: f32 = e;
205 try expect(@log(a) == 1 or @log(a) == @bitCast(f32, @as(u32, 0x3f7fffff)));
206 }
207 {
208 var a: f64 = e;
209 try expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));
210 }
211 {
212 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
213 var result = @log(v);
214 try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon));
215 try expect(math.approxEqAbs(f32, @log(@as(f32, 2.2)), result[1], epsilon));
216 try expect(math.approxEqAbs(f32, @log(@as(f32, 0.3)), result[2], epsilon));
217 try expect(math.approxEqAbs(f32, @log(@as(f32, 0.4)), result[3], epsilon));
218 }
219}
220
221test "@log2" {
222 comptime try testLog2();
223 try testLog2();
224}
225
226fn testLog2() !void {
227 // TODO test f128, and c_longdouble
228 // https://github.com/ziglang/zig/issues/4026
229 {
230 var a: f16 = 4;
231 try expect(@log2(a) == 2);
232 }
233 {
234 var a: f32 = 4;
235 try expect(@log2(a) == 2);
236 }
237 {
238 var a: f64 = 4;
239 try expect(@log2(a) == 2);
240 }
241 {
242 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
243 var result = @log2(v);
244 try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon));
245 try expect(math.approxEqAbs(f32, @log2(@as(f32, 2.2)), result[1], epsilon));
246 try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.3)), result[2], epsilon));
247 try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.4)), result[3], epsilon));
248 }
249}
250
251test "@log10" {
252 comptime try testLog10();
253 try testLog10();
254}
255
256fn testLog10() !void {
257 // TODO test f128, and c_longdouble
258 // https://github.com/ziglang/zig/issues/4026
259 {
260 var a: f16 = 100;
261 try expect(@log10(a) == 2);
262 }
263 {
264 var a: f32 = 100;
265 try expect(@log10(a) == 2);
266 }
267 {
268 var a: f64 = 1000;
269 try expect(@log10(a) == 3);
270 }
271 {
272 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
273 var result = @log10(v);
274 try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon));
275 try expect(math.approxEqAbs(f32, @log10(@as(f32, 2.2)), result[1], epsilon));
276 try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.3)), result[2], epsilon));
277 try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.4)), result[3], epsilon));
278 }
279}
280
281test "@fabs" {
282 comptime try testFabs();
283 try testFabs();
284}
285
286fn testFabs() !void {
287 // TODO test f128, and c_longdouble
288 // https://github.com/ziglang/zig/issues/4026
289 {
290 var a: f16 = -2.5;
291 var b: f16 = 2.5;
292 try expect(@fabs(a) == 2.5);
293 try expect(@fabs(b) == 2.5);
294 }
295 {
296 var a: f32 = -2.5;
297 var b: f32 = 2.5;
298 try expect(@fabs(a) == 2.5);
299 try expect(@fabs(b) == 2.5);
300 }
301 {
302 var a: f64 = -2.5;
303 var b: f64 = 2.5;
304 try expect(@fabs(a) == 2.5);
305 try expect(@fabs(b) == 2.5);
306 }
307 {
308 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
309 var result = @fabs(v);
310 try expect(math.approxEqAbs(f32, @fabs(@as(f32, 1.1)), result[0], epsilon));
311 try expect(math.approxEqAbs(f32, @fabs(@as(f32, -2.2)), result[1], epsilon));
312 try expect(math.approxEqAbs(f32, @fabs(@as(f32, 0.3)), result[2], epsilon));
313 try expect(math.approxEqAbs(f32, @fabs(@as(f32, -0.4)), result[3], epsilon));
314 }
315}
316
317test "@floor" {
318 comptime try testFloor();
319 try testFloor();
320}
321
322fn testFloor() !void {
323 // TODO test f128, and c_longdouble
324 // https://github.com/ziglang/zig/issues/4026
325 {
326 var a: f16 = 2.1;
327 try expect(@floor(a) == 2);
328 }
329 {
330 var a: f32 = 2.1;
331 try expect(@floor(a) == 2);
332 }
333 {
334 var a: f64 = 3.5;
335 try expect(@floor(a) == 3);
336 }
337 {
338 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
339 var result = @floor(v);
340 try expect(math.approxEqAbs(f32, @floor(@as(f32, 1.1)), result[0], epsilon));
341 try expect(math.approxEqAbs(f32, @floor(@as(f32, -2.2)), result[1], epsilon));
342 try expect(math.approxEqAbs(f32, @floor(@as(f32, 0.3)), result[2], epsilon));
343 try expect(math.approxEqAbs(f32, @floor(@as(f32, -0.4)), result[3], epsilon));
344 }
345}
346
347test "@ceil" {
348 comptime try testCeil();
349 try testCeil();
350}
351
352fn testCeil() !void {
353 // TODO test f128, and c_longdouble
354 // https://github.com/ziglang/zig/issues/4026
355 {
356 var a: f16 = 2.1;
357 try expect(@ceil(a) == 3);
358 }
359 {
360 var a: f32 = 2.1;
361 try expect(@ceil(a) == 3);
362 }
363 {
364 var a: f64 = 3.5;
365 try expect(@ceil(a) == 4);
366 }
367 {
368 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
369 var result = @ceil(v);
370 try expect(math.approxEqAbs(f32, @ceil(@as(f32, 1.1)), result[0], epsilon));
371 try expect(math.approxEqAbs(f32, @ceil(@as(f32, -2.2)), result[1], epsilon));
372 try expect(math.approxEqAbs(f32, @ceil(@as(f32, 0.3)), result[2], epsilon));
373 try expect(math.approxEqAbs(f32, @ceil(@as(f32, -0.4)), result[3], epsilon));
374 }
375}
376
377test "@trunc" {
378 comptime try testTrunc();
379 try testTrunc();
380}
381
382fn testTrunc() !void {
383 // TODO test f128, and c_longdouble
384 // https://github.com/ziglang/zig/issues/4026
385 {
386 var a: f16 = 2.1;
387 try expect(@trunc(a) == 2);
388 }
389 {
390 var a: f32 = 2.1;
391 try expect(@trunc(a) == 2);
392 }
393 {
394 var a: f64 = -3.5;
395 try expect(@trunc(a) == -3);
396 }
397 {
398 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
399 var result = @trunc(v);
400 try expect(math.approxEqAbs(f32, @trunc(@as(f32, 1.1)), result[0], epsilon));
401 try expect(math.approxEqAbs(f32, @trunc(@as(f32, -2.2)), result[1], epsilon));
402 try expect(math.approxEqAbs(f32, @trunc(@as(f32, 0.3)), result[2], epsilon));
403 try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));
404 }
405}
406
407test "floating point comparisons" {
408 try testFloatComparisons();
409 comptime try testFloatComparisons();
410}
411
412fn testFloatComparisons() !void {
413 inline for ([_]type{ f16, f32, f64, f128 }) |ty| {
414 // No decimal part
415 {
416 const x: ty = 1.0;
417 try expect(x == 1);
418 try expect(x != 0);
419 try expect(x > 0);
420 try expect(x < 2);
421 try expect(x >= 1);
422 try expect(x <= 1);
423 }
424 // Non-zero decimal part
425 {
426 const x: ty = 1.5;
427 try expect(x != 1);
428 try expect(x != 2);
429 try expect(x > 1);
430 try expect(x < 2);
431 try expect(x >= 1);
432 try expect(x <= 2);
433 }
434 }
435}
436
437test "different sized float comparisons" {
438 try testDifferentSizedFloatComparisons();
439 comptime try testDifferentSizedFloatComparisons();
440}
441
442fn testDifferentSizedFloatComparisons() !void {
443 var a: f16 = 1;
444 var b: f64 = 2;
445 try expect(a < b);
446}
447
448// TODO This is waiting on library support for the Windows build (not sure why the other's don't need it)
449//test "@nearbyint" {
450// comptime testNearbyInt();
451// testNearbyInt();
452//}
453
454//fn testNearbyInt() void {
455// // TODO test f16, f128, and c_longdouble
456// // https://github.com/ziglang/zig/issues/4026
457// {
458// var a: f32 = 2.1;
459// try expect(@nearbyint(a) == 2);
460// }
461// {
462// var a: f64 = -3.75;
463// try expect(@nearbyint(a) == -4);
464// }
465//}
test/stage1/behavior/fn.zig deleted-286
...@@ -1,286 +0,0 @@
1const std = @import("std");
2const testing = std.testing;
3const expect = testing.expect;
4const expectEqual = testing.expectEqual;
5
6test "params" {
7 try expect(testParamsAdd(22, 11) == 33);
8}
9fn testParamsAdd(a: i32, b: i32) i32 {
10 return a + b;
11}
12
13test "local variables" {
14 testLocVars(2);
15}
16fn testLocVars(b: i32) void {
17 const a: i32 = 1;
18 if (a + b != 3) unreachable;
19}
20
21test "void parameters" {
22 try voidFun(1, void{}, 2, {});
23}
24fn voidFun(a: i32, b: void, c: i32, d: void) !void {
25 const v = b;
26 const vv: void = if (a == 1) v else {};
27 try expect(a + c == 3);
28 return vv;
29}
30
31test "mutable local variables" {
32 var zero: i32 = 0;
33 try expect(zero == 0);
34
35 var i = @as(i32, 0);
36 while (i != 3) {
37 i += 1;
38 }
39 try expect(i == 3);
40}
41
42test "separate block scopes" {
43 {
44 const no_conflict: i32 = 5;
45 try expect(no_conflict == 5);
46 }
47
48 const c = x: {
49 const no_conflict = @as(i32, 10);
50 break :x no_conflict;
51 };
52 try expect(c == 10);
53}
54
55test "call function with empty string" {
56 acceptsString("");
57}
58
59fn acceptsString(foo: []u8) void {}
60
61fn @"weird function name"() i32 {
62 return 1234;
63}
64test "weird function name" {
65 try expect(@"weird function name"() == 1234);
66}
67
68test "implicit cast function unreachable return" {
69 wantsFnWithVoid(fnWithUnreachable);
70}
71
72fn wantsFnWithVoid(f: fn () void) void {}
73
74fn fnWithUnreachable() noreturn {
75 unreachable;
76}
77
78test "function pointers" {
79 const fns = [_]@TypeOf(fn1){
80 fn1,
81 fn2,
82 fn3,
83 fn4,
84 };
85 for (fns) |f, i| {
86 try expect(f() == @intCast(u32, i) + 5);
87 }
88}
89fn fn1() u32 {
90 return 5;
91}
92fn fn2() u32 {
93 return 6;
94}
95fn fn3() u32 {
96 return 7;
97}
98fn fn4() u32 {
99 return 8;
100}
101
102test "number literal as an argument" {
103 try numberLiteralArg(3);
104 comptime try numberLiteralArg(3);
105}
106
107fn numberLiteralArg(a: anytype) !void {
108 try expect(a == 3);
109}
110
111test "assign inline fn to const variable" {
112 const a = inlineFn;
113 a();
114}
115
116fn inlineFn() callconv(.Inline) void {}
117
118test "pass by non-copying value" {
119 try expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
120}
121
122const Point = struct {
123 x: i32,
124 y: i32,
125};
126
127fn addPointCoords(pt: Point) i32 {
128 return pt.x + pt.y;
129}
130
131test "pass by non-copying value through var arg" {
132 try expect((try addPointCoordsVar(Point{ .x = 1, .y = 2 })) == 3);
133}
134
135fn addPointCoordsVar(pt: anytype) !i32 {
136 comptime try expect(@TypeOf(pt) == Point);
137 return pt.x + pt.y;
138}
139
140test "pass by non-copying value as method" {
141 var pt = Point2{ .x = 1, .y = 2 };
142 try expect(pt.addPointCoords() == 3);
143}
144
145const Point2 = struct {
146 x: i32,
147 y: i32,
148
149 fn addPointCoords(self: Point2) i32 {
150 return self.x + self.y;
151 }
152};
153
154test "pass by non-copying value as method, which is generic" {
155 var pt = Point3{ .x = 1, .y = 2 };
156 try expect(pt.addPointCoords(i32) == 3);
157}
158
159const Point3 = struct {
160 x: i32,
161 y: i32,
162
163 fn addPointCoords(self: Point3, comptime T: type) i32 {
164 return self.x + self.y;
165 }
166};
167
168test "pass by non-copying value as method, at comptime" {
169 comptime {
170 var pt = Point2{ .x = 1, .y = 2 };
171 try expect(pt.addPointCoords() == 3);
172 }
173}
174
175fn outer(y: u32) fn (u32) u32 {
176 const Y = @TypeOf(y);
177 const st = struct {
178 fn get(z: u32) u32 {
179 return z + @sizeOf(Y);
180 }
181 };
182 return st.get;
183}
184
185test "return inner function which references comptime variable of outer function" {
186 var func = outer(10);
187 try expect(func(3) == 7);
188}
189
190test "extern struct with stdcallcc fn pointer" {
191 const S = extern struct {
192 ptr: fn () callconv(if (std.builtin.arch == .i386) .Stdcall else .C) i32,
193
194 fn foo() callconv(if (std.builtin.arch == .i386) .Stdcall else .C) i32 {
195 return 1234;
196 }
197 };
198
199 var s: S = undefined;
200 s.ptr = S.foo;
201 try expect(s.ptr() == 1234);
202}
203
204test "implicit cast fn call result to optional in field result" {
205 const S = struct {
206 fn entry() !void {
207 var x = Foo{
208 .field = optionalPtr(),
209 };
210 try expect(x.field.?.* == 999);
211 }
212
213 const glob: i32 = 999;
214
215 fn optionalPtr() *const i32 {
216 return &glob;
217 }
218
219 const Foo = struct {
220 field: ?*const i32,
221 };
222 };
223 try S.entry();
224 comptime try S.entry();
225}
226
227test "discard the result of a function that returns a struct" {
228 const S = struct {
229 fn entry() void {
230 _ = func();
231 }
232
233 fn func() Foo {
234 return undefined;
235 }
236
237 const Foo = struct {
238 a: u64,
239 b: u64,
240 };
241 };
242 S.entry();
243 comptime S.entry();
244}
245
246test "function call with anon list literal" {
247 const S = struct {
248 fn doTheTest() !void {
249 try consumeVec(.{ 9, 8, 7 });
250 }
251
252 fn consumeVec(vec: [3]f32) !void {
253 try expect(vec[0] == 9);
254 try expect(vec[1] == 8);
255 try expect(vec[2] == 7);
256 }
257 };
258 try S.doTheTest();
259 comptime try S.doTheTest();
260}
261
262test "ability to give comptime types and non comptime types to same parameter" {
263 const S = struct {
264 fn doTheTest() !void {
265 var x: i32 = 1;
266 try expect(foo(x) == 10);
267 try expect(foo(i32) == 20);
268 }
269
270 fn foo(arg: anytype) i32 {
271 if (@typeInfo(@TypeOf(arg)) == .Type and arg == i32) return 20;
272 return 9 + arg;
273 }
274 };
275 try S.doTheTest();
276 comptime try S.doTheTest();
277}
278
279test "function with inferred error set but returning no error" {
280 const S = struct {
281 fn foo() !void {}
282 };
283
284 const return_ty = @typeInfo(@TypeOf(S.foo)).Fn.return_type.?;
285 try expectEqual(0, @typeInfo(@typeInfo(return_ty).ErrorUnion.error_set).ErrorSet.?.len);
286}
test/stage1/behavior/fn_delegation.zig deleted-39
...@@ -1,39 +0,0 @@
1const expect = @import("std").testing.expect;
2
3const Foo = struct {
4 a: u64 = 10,
5
6 fn one(self: Foo) u64 {
7 return self.a + 1;
8 }
9
10 const two = __two;
11
12 fn __two(self: Foo) u64 {
13 return self.a + 2;
14 }
15
16 const three = __three;
17
18 const four = custom(Foo, 4);
19};
20
21fn __three(self: Foo) u64 {
22 return self.a + 3;
23}
24
25fn custom(comptime T: type, comptime num: u64) fn (T) u64 {
26 return struct {
27 fn function(self: T) u64 {
28 return self.a + num;
29 }
30 }.function;
31}
32
33test "fn delegation" {
34 const foo = Foo{};
35 try expect(foo.one() == 11);
36 try expect(foo.two() == 12);
37 try expect(foo.three() == 13);
38 try expect(foo.four() == 14);
39}
test/stage1/behavior/fn_in_struct_in_comptime.zig deleted-17
...@@ -1,17 +0,0 @@
1const expect = @import("std").testing.expect;
2
3fn get_foo() fn (*u8) usize {
4 comptime {
5 return struct {
6 fn func(ptr: *u8) usize {
7 var u = @ptrToInt(ptr);
8 return u;
9 }
10 }.func;
11 }
12}
13
14test "define a function in an anonymous struct in comptime" {
15 const foo = get_foo();
16 try expect(foo(@intToPtr(*u8, 12345)) == 12345);
17}
test/stage1/behavior/for.zig deleted-172
...@@ -1,172 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const mem = std.mem;
5
6test "continue in for loop" {
7 const array = [_]i32{
8 1,
9 2,
10 3,
11 4,
12 5,
13 };
14 var sum: i32 = 0;
15 for (array) |x| {
16 sum += x;
17 if (x < 3) {
18 continue;
19 }
20 break;
21 }
22 if (sum != 6) unreachable;
23}
24
25test "for loop with pointer elem var" {
26 const source = "abcdefg";
27 var target: [source.len]u8 = undefined;
28 mem.copy(u8, target[0..], source);
29 mangleString(target[0..]);
30 try expect(mem.eql(u8, &target, "bcdefgh"));
31
32 for (source) |*c, i|
33 try expect(@TypeOf(c) == *const u8);
34 for (target) |*c, i|
35 try expect(@TypeOf(c) == *u8);
36}
37
38fn mangleString(s: []u8) void {
39 for (s) |*c| {
40 c.* += 1;
41 }
42}
43
44test "basic for loop" {
45 const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
46
47 var buffer: [expected_result.len]u8 = undefined;
48 var buf_index: usize = 0;
49
50 const array = [_]u8{ 9, 8, 7, 6 };
51 for (array) |item| {
52 buffer[buf_index] = item;
53 buf_index += 1;
54 }
55 for (array) |item, index| {
56 buffer[buf_index] = @intCast(u8, index);
57 buf_index += 1;
58 }
59 const array_ptr = &array;
60 for (array_ptr) |item| {
61 buffer[buf_index] = item;
62 buf_index += 1;
63 }
64 for (array_ptr) |item, index| {
65 buffer[buf_index] = @intCast(u8, index);
66 buf_index += 1;
67 }
68 const unknown_size: []const u8 = &array;
69 for (unknown_size) |item| {
70 buffer[buf_index] = item;
71 buf_index += 1;
72 }
73 for (unknown_size) |item, index| {
74 buffer[buf_index] = @intCast(u8, index);
75 buf_index += 1;
76 }
77
78 try expect(mem.eql(u8, buffer[0..buf_index], &expected_result));
79}
80
81test "break from outer for loop" {
82 try testBreakOuter();
83 comptime try testBreakOuter();
84}
85
86fn testBreakOuter() !void {
87 var array = "aoeu";
88 var count: usize = 0;
89 outer: for (array) |_| {
90 for (array) |_| {
91 count += 1;
92 break :outer;
93 }
94 }
95 try expect(count == 1);
96}
97
98test "continue outer for loop" {
99 try testContinueOuter();
100 comptime try testContinueOuter();
101}
102
103fn testContinueOuter() !void {
104 var array = "aoeu";
105 var counter: usize = 0;
106 outer: for (array) |_| {
107 for (array) |_| {
108 counter += 1;
109 continue :outer;
110 }
111 }
112 try expect(counter == array.len);
113}
114
115test "2 break statements and an else" {
116 const S = struct {
117 fn entry(t: bool, f: bool) !void {
118 var buf: [10]u8 = undefined;
119 var ok = false;
120 ok = for (buf) |item| {
121 if (f) break false;
122 if (t) break true;
123 } else false;
124 try expect(ok);
125 }
126 };
127 try S.entry(true, false);
128 comptime try S.entry(true, false);
129}
130
131test "for with null and T peer types and inferred result location type" {
132 const S = struct {
133 fn doTheTest(slice: []const u8) !void {
134 if (for (slice) |item| {
135 if (item == 10) {
136 break item;
137 }
138 } else null) |v| {
139 @panic("fail");
140 }
141 }
142 };
143 try S.doTheTest(&[_]u8{ 1, 2 });
144 comptime try S.doTheTest(&[_]u8{ 1, 2 });
145}
146
147test "for copies its payload" {
148 const S = struct {
149 fn doTheTest() !void {
150 var x = [_]usize{ 1, 2, 3 };
151 for (x) |value, i| {
152 // Modify the original array
153 x[i] += 99;
154 try expectEqual(value, i + 1);
155 }
156 }
157 };
158 try S.doTheTest();
159 comptime try S.doTheTest();
160}
161
162test "for on slice with allowzero ptr" {
163 const S = struct {
164 fn doTheTest(slice: []const u8) !void {
165 var ptr = @ptrCast([*]allowzero const u8, slice.ptr)[0..slice.len];
166 for (ptr) |x, i| try expect(x == i + 1);
167 for (ptr) |*x, i| try expect(x.* == i + 1);
168 }
169 };
170 try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
171 comptime try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
172}
test/stage1/behavior/generics.zig deleted-169
...@@ -1,169 +0,0 @@
1const std = @import("std");
2const testing = std.testing;
3const expect = testing.expect;
4const expectEqual = testing.expectEqual;
5
6test "simple generic fn" {
7 try expect(max(i32, 3, -1) == 3);
8 try expect(max(f32, 0.123, 0.456) == 0.456);
9 try expect(add(2, 3) == 5);
10}
11
12fn max(comptime T: type, a: T, b: T) T {
13 return if (a > b) a else b;
14}
15
16fn add(comptime a: i32, b: i32) i32 {
17 return (comptime a) + b;
18}
19
20const the_max = max(u32, 1234, 5678);
21test "compile time generic eval" {
22 try expect(the_max == 5678);
23}
24
25fn gimmeTheBigOne(a: u32, b: u32) u32 {
26 return max(u32, a, b);
27}
28
29fn shouldCallSameInstance(a: u32, b: u32) u32 {
30 return max(u32, a, b);
31}
32
33fn sameButWithFloats(a: f64, b: f64) f64 {
34 return max(f64, a, b);
35}
36
37test "fn with comptime args" {
38 try expect(gimmeTheBigOne(1234, 5678) == 5678);
39 try expect(shouldCallSameInstance(34, 12) == 34);
40 try expect(sameButWithFloats(0.43, 0.49) == 0.49);
41}
42
43test "var params" {
44 try expect(max_i32(12, 34) == 34);
45 try expect(max_f64(1.2, 3.4) == 3.4);
46}
47
48comptime {
49 try expect(max_i32(12, 34) == 34);
50 try expect(max_f64(1.2, 3.4) == 3.4);
51}
52
53fn max_var(a: anytype, b: anytype) @TypeOf(a + b) {
54 return if (a > b) a else b;
55}
56
57fn max_i32(a: i32, b: i32) i32 {
58 return max_var(a, b);
59}
60
61fn max_f64(a: f64, b: f64) f64 {
62 return max_var(a, b);
63}
64
65pub fn List(comptime T: type) type {
66 return SmallList(T, 8);
67}
68
69pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
70 return struct {
71 items: []T,
72 length: usize,
73 prealloc_items: [STATIC_SIZE]T,
74 };
75}
76
77test "function with return type type" {
78 var list: List(i32) = undefined;
79 var list2: List(i32) = undefined;
80 list.length = 10;
81 list2.length = 10;
82 try expect(list.prealloc_items.len == 8);
83 try expect(list2.prealloc_items.len == 8);
84}
85
86test "generic struct" {
87 var a1 = GenNode(i32){
88 .value = 13,
89 .next = null,
90 };
91 var b1 = GenNode(bool){
92 .value = true,
93 .next = null,
94 };
95 try expect(a1.value == 13);
96 try expect(a1.value == a1.getVal());
97 try expect(b1.getVal());
98}
99fn GenNode(comptime T: type) type {
100 return struct {
101 value: T,
102 next: ?*GenNode(T),
103 fn getVal(n: *const GenNode(T)) T {
104 return n.value;
105 }
106 };
107}
108
109test "const decls in struct" {
110 try expect(GenericDataThing(3).count_plus_one == 4);
111}
112fn GenericDataThing(comptime count: isize) type {
113 return struct {
114 const count_plus_one = count + 1;
115 };
116}
117
118test "use generic param in generic param" {
119 try expect(aGenericFn(i32, 3, 4) == 7);
120}
121fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
122 return a + b;
123}
124
125test "generic fn with implicit cast" {
126 try expect(getFirstByte(u8, &[_]u8{13}) == 13);
127 try expect(getFirstByte(u16, &[_]u16{
128 0,
129 13,
130 }) == 0);
131}
132fn getByte(ptr: ?*const u8) u8 {
133 return ptr.?.*;
134}
135fn getFirstByte(comptime T: type, mem: []const T) u8 {
136 return getByte(@ptrCast(*const u8, &mem[0]));
137}
138
139const foos = [_]fn (anytype) bool{
140 foo1,
141 foo2,
142};
143
144fn foo1(arg: anytype) bool {
145 return arg;
146}
147fn foo2(arg: anytype) bool {
148 return !arg;
149}
150
151test "array of generic fns" {
152 try expect(foos[0](true));
153 try expect(!foos[1](true));
154}
155
156test "generic fn keeps non-generic parameter types" {
157 const A = 128;
158
159 const S = struct {
160 fn f(comptime T: type, s: []T) !void {
161 try expect(A != @typeInfo(@TypeOf(s)).Pointer.alignment);
162 }
163 };
164
165 // The compiler monomorphizes `S.f` for `T=u8` on its first use, check that
166 // `x` type not affect `s` parameter type.
167 var x: [16]u8 align(A) = undefined;
168 try S.f(u8, &x);
169}
test/stage1/behavior/hasdecl.zig deleted-21
...@@ -1,21 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const Foo = @import("hasdecl/foo.zig");
5
6const Bar = struct {
7 nope: i32,
8
9 const hi = 1;
10 pub var blah = "xxx";
11};
12
13test "@hasDecl" {
14 try expect(@hasDecl(Foo, "public_thing"));
15 try expect(!@hasDecl(Foo, "private_thing"));
16 try expect(!@hasDecl(Foo, "no_thing"));
17
18 try expect(@hasDecl(Bar, "hi"));
19 try expect(@hasDecl(Bar, "blah"));
20 try expect(!@hasDecl(Bar, "nope"));
21}
test/stage1/behavior/hasdecl/foo.zig deleted-2
...@@ -1,2 +0,0 @@
1pub const public_thing = 42;
2const private_thing = 666;
test/stage1/behavior/hasfield.zig deleted-37
...@@ -1,37 +0,0 @@
1const expect = @import("std").testing.expect;
2const builtin = @import("builtin");
3
4test "@hasField" {
5 const struc = struct {
6 a: i32,
7 b: []u8,
8
9 pub const nope = 1;
10 };
11 try expect(@hasField(struc, "a") == true);
12 try expect(@hasField(struc, "b") == true);
13 try expect(@hasField(struc, "non-existant") == false);
14 try expect(@hasField(struc, "nope") == false);
15
16 const unin = union {
17 a: u64,
18 b: []u16,
19
20 pub const nope = 1;
21 };
22 try expect(@hasField(unin, "a") == true);
23 try expect(@hasField(unin, "b") == true);
24 try expect(@hasField(unin, "non-existant") == false);
25 try expect(@hasField(unin, "nope") == false);
26
27 const enm = enum {
28 a,
29 b,
30
31 pub const nope = 1;
32 };
33 try expect(@hasField(enm, "a") == true);
34 try expect(@hasField(enm, "b") == true);
35 try expect(@hasField(enm, "non-existant") == false);
36 try expect(@hasField(enm, "nope") == false);
37}
test/stage1/behavior/if.zig deleted-109
...@@ -1,109 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4
5test "if statements" {
6 shouldBeEqual(1, 1);
7 firstEqlThird(2, 1, 2);
8}
9fn shouldBeEqual(a: i32, b: i32) void {
10 if (a != b) {
11 unreachable;
12 } else {
13 return;
14 }
15}
16fn firstEqlThird(a: i32, b: i32, c: i32) void {
17 if (a == b) {
18 unreachable;
19 } else if (b == c) {
20 unreachable;
21 } else if (a == c) {
22 return;
23 } else {
24 unreachable;
25 }
26}
27
28test "else if expression" {
29 try expect(elseIfExpressionF(1) == 1);
30}
31fn elseIfExpressionF(c: u8) u8 {
32 if (c == 0) {
33 return 0;
34 } else if (c == 1) {
35 return 1;
36 } else {
37 return @as(u8, 2);
38 }
39}
40
41// #2297
42var global_with_val: anyerror!u32 = 0;
43var global_with_err: anyerror!u32 = error.SomeError;
44
45test "unwrap mutable global var" {
46 if (global_with_val) |v| {
47 try expect(v == 0);
48 } else |e| {
49 unreachable;
50 }
51 if (global_with_err) |_| {
52 unreachable;
53 } else |e| {
54 try expect(e == error.SomeError);
55 }
56}
57
58test "labeled break inside comptime if inside runtime if" {
59 var answer: i32 = 0;
60 var c = true;
61 if (c) {
62 answer = if (true) blk: {
63 break :blk @as(i32, 42);
64 };
65 }
66 try expect(answer == 42);
67}
68
69test "const result loc, runtime if cond, else unreachable" {
70 const Num = enum {
71 One,
72 Two,
73 };
74
75 var t = true;
76 const x = if (t) Num.Two else unreachable;
77 try expect(x == .Two);
78}
79
80test "if prongs cast to expected type instead of peer type resolution" {
81 const S = struct {
82 fn doTheTest(f: bool) !void {
83 var x: i32 = 0;
84 x = if (f) 1 else 2;
85 try expect(x == 2);
86
87 var b = true;
88 const y: i32 = if (b) 1 else 2;
89 try expect(y == 1);
90 }
91 };
92 try S.doTheTest(false);
93 comptime try S.doTheTest(false);
94}
95
96test "while copies its payload" {
97 const S = struct {
98 fn doTheTest() !void {
99 var tmp: ?i32 = 10;
100 if (tmp) |value| {
101 // Modify the original variable
102 tmp = null;
103 try expectEqual(@as(i32, 10), value);
104 } else unreachable;
105 }
106 };
107 try S.doTheTest();
108 comptime try S.doTheTest();
109}
test/stage1/behavior/import.zig deleted-22
...@@ -1,22 +0,0 @@
1const expect = @import("std").testing.expect;
2const expectEqual = @import("std").testing.expectEqual;
3const a_namespace = @import("import/a_namespace.zig");
4
5test "call fn via namespace lookup" {
6 try expectEqual(@as(i32, 1234), a_namespace.foo());
7}
8
9test "importing the same thing gives the same import" {
10 try expect(@import("std") == @import("std"));
11}
12
13test "import in non-toplevel scope" {
14 const S = struct {
15 usingnamespace @import("import/a_namespace.zig");
16 };
17 try expectEqual(@as(i32, 1234), S.foo());
18}
19
20test "import empty file" {
21 const empty = @import("import/empty.zig");
22}
test/stage1/behavior/import/a_namespace.zig deleted-3
...@@ -1,3 +0,0 @@
1pub fn foo() i32 {
2 return 1234;
3}
test/stage1/behavior/import/empty.zig deleted
test/stage1/behavior/incomplete_struct_param_tld.zig deleted-30
...@@ -1,30 +0,0 @@
1const expect = @import("std").testing.expect;
2
3const A = struct {
4 b: B,
5};
6
7const B = struct {
8 c: C,
9};
10
11const C = struct {
12 x: i32,
13
14 fn d(c: *const C) i32 {
15 return c.x;
16 }
17};
18
19fn foo(a: A) i32 {
20 return a.b.c.d();
21}
22
23test "incomplete struct param top level declaration" {
24 const a = A{
25 .b = B{
26 .c = C{ .x = 13 },
27 },
28 };
29 try expect(foo(a) == 13);
30}
test/stage1/behavior/inttoptr.zig deleted-22
...@@ -1,22 +0,0 @@
1test "casting random address to function pointer" {
2 randomAddressToFunction();
3 comptime randomAddressToFunction();
4}
5
6fn randomAddressToFunction() void {
7 var addr: usize = 0xdeadbeef;
8 var ptr = @intToPtr(fn () void, addr);
9}
10
11test "mutate through ptr initialized with constant intToPtr value" {
12 forceCompilerAnalyzeBranchHardCodedPtrDereference(false);
13}
14
15fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
16 const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef);
17 if (x) {
18 hardCodedP.* = hardCodedP.* | 10;
19 } else {
20 return;
21 }
22}
test/stage1/behavior/ir_block_deps.zig deleted-21
...@@ -1,21 +0,0 @@
1const expect = @import("std").testing.expect;
2
3fn foo(id: u64) !i32 {
4 return switch (id) {
5 1 => getErrInt(),
6 2 => {
7 const size = try getErrInt();
8 return try getErrInt();
9 },
10 else => error.ItBroke,
11 };
12}
13
14fn getErrInt() anyerror!i32 {
15 return 0;
16}
17
18test "ir block deps" {
19 try expect((foo(1) catch unreachable) == 0);
20 try expect((foo(2) catch unreachable) == 0);
21}
test/stage1/behavior/math.zig deleted-872
...@@ -1,872 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const expectEqualSlices = std.testing.expectEqualSlices;
5const maxInt = std.math.maxInt;
6const minInt = std.math.minInt;
7const mem = std.mem;
8
9test "division" {
10 try testDivision();
11 comptime try testDivision();
12}
13fn testDivision() !void {
14 try expect(div(u32, 13, 3) == 4);
15 try expect(div(f16, 1.0, 2.0) == 0.5);
16 try expect(div(f32, 1.0, 2.0) == 0.5);
17
18 try expect(divExact(u32, 55, 11) == 5);
19 try expect(divExact(i32, -55, 11) == -5);
20 try expect(divExact(f16, 55.0, 11.0) == 5.0);
21 try expect(divExact(f16, -55.0, 11.0) == -5.0);
22 try expect(divExact(f32, 55.0, 11.0) == 5.0);
23 try expect(divExact(f32, -55.0, 11.0) == -5.0);
24
25 try expect(divFloor(i32, 5, 3) == 1);
26 try expect(divFloor(i32, -5, 3) == -2);
27 try expect(divFloor(f16, 5.0, 3.0) == 1.0);
28 try expect(divFloor(f16, -5.0, 3.0) == -2.0);
29 try expect(divFloor(f32, 5.0, 3.0) == 1.0);
30 try expect(divFloor(f32, -5.0, 3.0) == -2.0);
31 try expect(divFloor(i32, -0x80000000, -2) == 0x40000000);
32 try expect(divFloor(i32, 0, -0x80000000) == 0);
33 try expect(divFloor(i32, -0x40000001, 0x40000000) == -2);
34 try expect(divFloor(i32, -0x80000000, 1) == -0x80000000);
35 try expect(divFloor(i32, 10, 12) == 0);
36 try expect(divFloor(i32, -14, 12) == -2);
37 try expect(divFloor(i32, -2, 12) == -1);
38
39 try expect(divTrunc(i32, 5, 3) == 1);
40 try expect(divTrunc(i32, -5, 3) == -1);
41 try expect(divTrunc(f16, 5.0, 3.0) == 1.0);
42 try expect(divTrunc(f16, -5.0, 3.0) == -1.0);
43 try expect(divTrunc(f32, 5.0, 3.0) == 1.0);
44 try expect(divTrunc(f32, -5.0, 3.0) == -1.0);
45 try expect(divTrunc(f64, 5.0, 3.0) == 1.0);
46 try expect(divTrunc(f64, -5.0, 3.0) == -1.0);
47 try expect(divTrunc(i32, 10, 12) == 0);
48 try expect(divTrunc(i32, -14, 12) == -1);
49 try expect(divTrunc(i32, -2, 12) == 0);
50
51 try expect(mod(i32, 10, 12) == 10);
52 try expect(mod(i32, -14, 12) == 10);
53 try expect(mod(i32, -2, 12) == 10);
54
55 comptime {
56 try expect(
57 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
58 );
59 try expect(
60 @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
61 );
62 try expect(
63 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
64 );
65 try expect(
66 @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
67 );
68 try expect(
69 @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
70 );
71 try expect(
72 @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
73 );
74 try expect(
75 4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
76 );
77 }
78}
79fn div(comptime T: type, a: T, b: T) T {
80 return a / b;
81}
82fn divExact(comptime T: type, a: T, b: T) T {
83 return @divExact(a, b);
84}
85fn divFloor(comptime T: type, a: T, b: T) T {
86 return @divFloor(a, b);
87}
88fn divTrunc(comptime T: type, a: T, b: T) T {
89 return @divTrunc(a, b);
90}
91fn mod(comptime T: type, a: T, b: T) T {
92 return @mod(a, b);
93}
94
95test "@addWithOverflow" {
96 var result: u8 = undefined;
97 try expect(@addWithOverflow(u8, 250, 100, &result));
98 try expect(!@addWithOverflow(u8, 100, 150, &result));
99 try expect(result == 250);
100}
101
102// TODO test mulWithOverflow
103// TODO test subWithOverflow
104
105test "@shlWithOverflow" {
106 var result: u16 = undefined;
107 try expect(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
108 try expect(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
109 try expect(result == 0b1011111111111100);
110}
111
112test "@*WithOverflow with u0 values" {
113 var result: u0 = undefined;
114 try expect(!@addWithOverflow(u0, 0, 0, &result));
115 try expect(!@subWithOverflow(u0, 0, 0, &result));
116 try expect(!@mulWithOverflow(u0, 0, 0, &result));
117 try expect(!@shlWithOverflow(u0, 0, 0, &result));
118}
119
120test "@clz" {
121 try testClz();
122 comptime try testClz();
123}
124
125fn testClz() !void {
126 try expect(clz(u8, 0b10001010) == 0);
127 try expect(clz(u8, 0b00001010) == 4);
128 try expect(clz(u8, 0b00011010) == 3);
129 try expect(clz(u8, 0b00000000) == 8);
130 try expect(clz(u128, 0xffffffffffffffff) == 64);
131 try expect(clz(u128, 0x10000000000000000) == 63);
132}
133
134fn clz(comptime T: type, x: T) usize {
135 return @clz(T, x);
136}
137
138test "@ctz" {
139 try testCtz();
140 comptime try testCtz();
141}
142
143fn testCtz() !void {
144 try expect(ctz(u8, 0b10100000) == 5);
145 try expect(ctz(u8, 0b10001010) == 1);
146 try expect(ctz(u8, 0b00000000) == 8);
147 try expect(ctz(u16, 0b00000000) == 16);
148}
149
150fn ctz(comptime T: type, x: T) usize {
151 return @ctz(T, x);
152}
153
154test "assignment operators" {
155 var i: u32 = 0;
156 i += 5;
157 try expect(i == 5);
158 i -= 2;
159 try expect(i == 3);
160 i *= 20;
161 try expect(i == 60);
162 i /= 3;
163 try expect(i == 20);
164 i %= 11;
165 try expect(i == 9);
166 i <<= 1;
167 try expect(i == 18);
168 i >>= 2;
169 try expect(i == 4);
170 i = 6;
171 i &= 5;
172 try expect(i == 4);
173 i ^= 6;
174 try expect(i == 2);
175 i = 6;
176 i |= 3;
177 try expect(i == 7);
178}
179
180test "three expr in a row" {
181 try testThreeExprInARow(false, true);
182 comptime try testThreeExprInARow(false, true);
183}
184fn testThreeExprInARow(f: bool, t: bool) !void {
185 try assertFalse(f or f or f);
186 try assertFalse(t and t and f);
187 try assertFalse(1 | 2 | 4 != 7);
188 try assertFalse(3 ^ 6 ^ 8 != 13);
189 try assertFalse(7 & 14 & 28 != 4);
190 try assertFalse(9 << 1 << 2 != 9 << 3);
191 try assertFalse(90 >> 1 >> 2 != 90 >> 3);
192 try assertFalse(100 - 1 + 1000 != 1099);
193 try assertFalse(5 * 4 / 2 % 3 != 1);
194 try assertFalse(@as(i32, @as(i32, 5)) != 5);
195 try assertFalse(!!false);
196 try assertFalse(@as(i32, 7) != --(@as(i32, 7)));
197}
198fn assertFalse(b: bool) !void {
199 try expect(!b);
200}
201
202test "const number literal" {
203 const one = 1;
204 const eleven = ten + one;
205
206 try expect(eleven == 11);
207}
208const ten = 10;
209
210test "unsigned wrapping" {
211 try testUnsignedWrappingEval(maxInt(u32));
212 comptime try testUnsignedWrappingEval(maxInt(u32));
213}
214fn testUnsignedWrappingEval(x: u32) !void {
215 const zero = x +% 1;
216 try expect(zero == 0);
217 const orig = zero -% 1;
218 try expect(orig == maxInt(u32));
219}
220
221test "signed wrapping" {
222 try testSignedWrappingEval(maxInt(i32));
223 comptime try testSignedWrappingEval(maxInt(i32));
224}
225fn testSignedWrappingEval(x: i32) !void {
226 const min_val = x +% 1;
227 try expect(min_val == minInt(i32));
228 const max_val = min_val -% 1;
229 try expect(max_val == maxInt(i32));
230}
231
232test "signed negation wrapping" {
233 try testSignedNegationWrappingEval(minInt(i16));
234 comptime try testSignedNegationWrappingEval(minInt(i16));
235}
236fn testSignedNegationWrappingEval(x: i16) !void {
237 try expect(x == -32768);
238 const neg = -%x;
239 try expect(neg == -32768);
240}
241
242test "unsigned negation wrapping" {
243 try testUnsignedNegationWrappingEval(1);
244 comptime try testUnsignedNegationWrappingEval(1);
245}
246fn testUnsignedNegationWrappingEval(x: u16) !void {
247 try expect(x == 1);
248 const neg = -%x;
249 try expect(neg == maxInt(u16));
250}
251
252test "unsigned 64-bit division" {
253 try test_u64_div();
254 comptime try test_u64_div();
255}
256fn test_u64_div() !void {
257 const result = divWithResult(1152921504606846976, 34359738365);
258 try expect(result.quotient == 33554432);
259 try expect(result.remainder == 100663296);
260}
261fn divWithResult(a: u64, b: u64) DivResult {
262 return DivResult{
263 .quotient = a / b,
264 .remainder = a % b,
265 };
266}
267const DivResult = struct {
268 quotient: u64,
269 remainder: u64,
270};
271
272test "binary not" {
273 try expect(comptime x: {
274 break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101;
275 });
276 try expect(comptime x: {
277 break :x ~@as(u64, 2147483647) == 18446744071562067968;
278 });
279 try testBinaryNot(0b1010101010101010);
280}
281
282fn testBinaryNot(x: u16) !void {
283 try expect(~x == 0b0101010101010101);
284}
285
286test "small int addition" {
287 var x: u2 = 0;
288 try expect(x == 0);
289
290 x += 1;
291 try expect(x == 1);
292
293 x += 1;
294 try expect(x == 2);
295
296 x += 1;
297 try expect(x == 3);
298
299 var result: @TypeOf(x) = 3;
300 try expect(@addWithOverflow(@TypeOf(x), x, 1, &result));
301
302 try expect(result == 0);
303}
304
305test "float equality" {
306 const x: f64 = 0.012;
307 const y: f64 = x + 1.0;
308
309 try testFloatEqualityImpl(x, y);
310 comptime try testFloatEqualityImpl(x, y);
311}
312
313fn testFloatEqualityImpl(x: f64, y: f64) !void {
314 const y2 = x + 1.0;
315 try expect(y == y2);
316}
317
318test "allow signed integer division/remainder when values are comptime known and positive or exact" {
319 try expect(5 / 3 == 1);
320 try expect(-5 / -3 == 1);
321 try expect(-6 / 3 == -2);
322
323 try expect(5 % 3 == 2);
324 try expect(-6 % 3 == 0);
325}
326
327test "hex float literal parsing" {
328 comptime try expect(0x1.0 == 1.0);
329}
330
331test "quad hex float literal parsing in range" {
332 const a = 0x1.af23456789bbaaab347645365cdep+5;
333 const b = 0x1.dedafcff354b6ae9758763545432p-9;
334 const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534;
335 const d = 0x1.edcbff8ad76ab5bf46463233214fp-435;
336}
337
338test "quad hex float literal parsing accurate" {
339 const a: f128 = 0x1.1111222233334444555566667777p+0;
340
341 // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
342 const expected: u128 = 0x3fff1111222233334444555566667777;
343 try expect(@bitCast(u128, a) == expected);
344
345 // non-normalized
346 const b: f128 = 0x11.111222233334444555566667777p-4;
347 try expect(@bitCast(u128, b) == expected);
348
349 const S = struct {
350 fn doTheTest() !void {
351 {
352 var f: f128 = 0x1.2eab345678439abcdefea56782346p+5;
353 try expect(@bitCast(u128, f) == 0x40042eab345678439abcdefea5678234);
354 }
355 {
356 var f: f128 = 0x1.edcb34a235253948765432134674fp-1;
357 try expect(@bitCast(u128, f) == 0x3ffeedcb34a235253948765432134674);
358 }
359 {
360 var f: f128 = 0x1.353e45674d89abacc3a2ebf3ff4ffp-50;
361 try expect(@bitCast(u128, f) == 0x3fcd353e45674d89abacc3a2ebf3ff50);
362 }
363 {
364 var f: f128 = 0x1.ed8764648369535adf4be3214567fp-9;
365 try expect(@bitCast(u128, f) == 0x3ff6ed8764648369535adf4be3214568);
366 }
367 const exp2ft = [_]f64{
368 0x1.6a09e667f3bcdp-1,
369 0x1.7a11473eb0187p-1,
370 0x1.8ace5422aa0dbp-1,
371 0x1.9c49182a3f090p-1,
372 0x1.ae89f995ad3adp-1,
373 0x1.c199bdd85529cp-1,
374 0x1.d5818dcfba487p-1,
375 0x1.ea4afa2a490dap-1,
376 0x1.0000000000000p+0,
377 0x1.0b5586cf9890fp+0,
378 0x1.172b83c7d517bp+0,
379 0x1.2387a6e756238p+0,
380 0x1.306fe0a31b715p+0,
381 0x1.3dea64c123422p+0,
382 0x1.4bfdad5362a27p+0,
383 0x1.5ab07dd485429p+0,
384 0x1.8p23,
385 0x1.62e430p-1,
386 0x1.ebfbe0p-3,
387 0x1.c6b348p-5,
388 0x1.3b2c9cp-7,
389 0x1.0p127,
390 -0x1.0p-149,
391 };
392
393 const answers = [_]u64{
394 0x3fe6a09e667f3bcd,
395 0x3fe7a11473eb0187,
396 0x3fe8ace5422aa0db,
397 0x3fe9c49182a3f090,
398 0x3feae89f995ad3ad,
399 0x3fec199bdd85529c,
400 0x3fed5818dcfba487,
401 0x3feea4afa2a490da,
402 0x3ff0000000000000,
403 0x3ff0b5586cf9890f,
404 0x3ff172b83c7d517b,
405 0x3ff2387a6e756238,
406 0x3ff306fe0a31b715,
407 0x3ff3dea64c123422,
408 0x3ff4bfdad5362a27,
409 0x3ff5ab07dd485429,
410 0x4168000000000000,
411 0x3fe62e4300000000,
412 0x3fcebfbe00000000,
413 0x3fac6b3480000000,
414 0x3f83b2c9c0000000,
415 0x47e0000000000000,
416 0xb6a0000000000000,
417 };
418
419 for (exp2ft) |x, i| {
420 try expect(@bitCast(u64, x) == answers[i]);
421 }
422 }
423 };
424 try S.doTheTest();
425 comptime try S.doTheTest();
426}
427
428test "underscore separator parsing" {
429 try expect(0_0_0_0 == 0);
430 try expect(1_234_567 == 1234567);
431 try expect(001_234_567 == 1234567);
432 try expect(0_0_1_2_3_4_5_6_7 == 1234567);
433
434 try expect(0b0_0_0_0 == 0);
435 try expect(0b1010_1010 == 0b10101010);
436 try expect(0b0000_1010_1010 == 0b10101010);
437 try expect(0b1_0_1_0_1_0_1_0 == 0b10101010);
438
439 try expect(0o0_0_0_0 == 0);
440 try expect(0o1010_1010 == 0o10101010);
441 try expect(0o0000_1010_1010 == 0o10101010);
442 try expect(0o1_0_1_0_1_0_1_0 == 0o10101010);
443
444 try expect(0x0_0_0_0 == 0);
445 try expect(0x1010_1010 == 0x10101010);
446 try expect(0x0000_1010_1010 == 0x10101010);
447 try expect(0x1_0_1_0_1_0_1_0 == 0x10101010);
448
449 try expect(123_456.789_000e1_0 == 123456.789000e10);
450 try expect(0_1_2_3_4_5_6.7_8_9_0_0_0e0_0_1_0 == 123456.789000e10);
451
452 try expect(0x1234_5678.9ABC_DEF0p-1_0 == 0x12345678.9ABCDEF0p-10);
453 try expect(0x1_2_3_4_5_6_7_8.9_A_B_C_D_E_F_0p-0_0_0_1_0 == 0x12345678.9ABCDEF0p-10);
454}
455
456test "hex float literal within range" {
457 const a = 0x1.0p16383;
458 const b = 0x0.1p16387;
459 const c = 0x1.0p-16382;
460}
461
462test "truncating shift left" {
463 try testShlTrunc(maxInt(u16));
464 comptime try testShlTrunc(maxInt(u16));
465}
466fn testShlTrunc(x: u16) !void {
467 const shifted = x << 1;
468 try expect(shifted == 65534);
469}
470
471test "truncating shift right" {
472 try testShrTrunc(maxInt(u16));
473 comptime try testShrTrunc(maxInt(u16));
474}
475fn testShrTrunc(x: u16) !void {
476 const shifted = x >> 1;
477 try expect(shifted == 32767);
478}
479
480test "exact shift left" {
481 try testShlExact(0b00110101);
482 comptime try testShlExact(0b00110101);
483}
484fn testShlExact(x: u8) !void {
485 const shifted = @shlExact(x, 2);
486 try expect(shifted == 0b11010100);
487}
488
489test "exact shift right" {
490 try testShrExact(0b10110100);
491 comptime try testShrExact(0b10110100);
492}
493fn testShrExact(x: u8) !void {
494 const shifted = @shrExact(x, 2);
495 try expect(shifted == 0b00101101);
496}
497
498test "shift left/right on u0 operand" {
499 const S = struct {
500 fn doTheTest() !void {
501 var x: u0 = 0;
502 var y: u0 = 0;
503 try expectEqual(@as(u0, 0), x << 0);
504 try expectEqual(@as(u0, 0), x >> 0);
505 try expectEqual(@as(u0, 0), x << y);
506 try expectEqual(@as(u0, 0), x >> y);
507 try expectEqual(@as(u0, 0), @shlExact(x, 0));
508 try expectEqual(@as(u0, 0), @shrExact(x, 0));
509 try expectEqual(@as(u0, 0), @shlExact(x, y));
510 try expectEqual(@as(u0, 0), @shrExact(x, y));
511 }
512 };
513 try S.doTheTest();
514 comptime try S.doTheTest();
515}
516
517test "comptime_int addition" {
518 comptime {
519 try expect(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
520 try expect(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
521 }
522}
523
524test "comptime_int multiplication" {
525 comptime {
526 try expect(
527 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
528 );
529 try expect(
530 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
531 );
532 }
533}
534
535test "comptime_int shifting" {
536 comptime {
537 try expect((@as(u128, 1) << 127) == 0x80000000000000000000000000000000);
538 }
539}
540
541test "comptime_int multi-limb shift and mask" {
542 comptime {
543 var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
544
545 try expect(@as(u32, a & 0xffffffff) == 0xaaaaaaab);
546 a >>= 32;
547 try expect(@as(u32, a & 0xffffffff) == 0xeeeeeeef);
548 a >>= 32;
549 try expect(@as(u32, a & 0xffffffff) == 0xa0000001);
550 a >>= 32;
551 try expect(@as(u32, a & 0xffffffff) == 0xefffffff);
552 a >>= 32;
553
554 try expect(a == 0);
555 }
556}
557
558test "comptime_int multi-limb partial shift right" {
559 comptime {
560 var a = 0x1ffffffffeeeeeeee;
561 a >>= 16;
562 try expect(a == 0x1ffffffffeeee);
563 }
564}
565
566test "xor" {
567 try test_xor();
568 comptime try test_xor();
569}
570
571fn test_xor() !void {
572 try expect(0xFF ^ 0x00 == 0xFF);
573 try expect(0xF0 ^ 0x0F == 0xFF);
574 try expect(0xFF ^ 0xF0 == 0x0F);
575 try expect(0xFF ^ 0x0F == 0xF0);
576 try expect(0xFF ^ 0xFF == 0x00);
577}
578
579test "comptime_int xor" {
580 comptime {
581 try expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
582 try expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
583 try expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
584 try expect(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
585 try expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
586 try expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
587 try expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
588 try expect(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
589 }
590}
591
592test "f128" {
593 try test_f128();
594 comptime try test_f128();
595}
596
597fn make_f128(x: f128) f128 {
598 return x;
599}
600
601fn test_f128() !void {
602 try expect(@sizeOf(f128) == 16);
603 try expect(make_f128(1.0) == 1.0);
604 try expect(make_f128(1.0) != 1.1);
605 try expect(make_f128(1.0) > 0.9);
606 try expect(make_f128(1.0) >= 0.9);
607 try expect(make_f128(1.0) >= 1.0);
608 try should_not_be_zero(1.0);
609}
610
611fn should_not_be_zero(x: f128) !void {
612 try expect(x != 0.0);
613}
614
615test "comptime float rem int" {
616 comptime {
617 var x = @as(f32, 1) % 2;
618 try expect(x == 1.0);
619 }
620}
621
622test "remainder division" {
623 comptime try remdiv(f16);
624 comptime try remdiv(f32);
625 comptime try remdiv(f64);
626 comptime try remdiv(f128);
627 try remdiv(f16);
628 try remdiv(f64);
629 try remdiv(f128);
630}
631
632fn remdiv(comptime T: type) !void {
633 try expect(@as(T, 1) == @as(T, 1) % @as(T, 2));
634 try expect(@as(T, 1) == @as(T, 7) % @as(T, 3));
635}
636
637test "@sqrt" {
638 try testSqrt(f64, 12.0);
639 comptime try testSqrt(f64, 12.0);
640 try testSqrt(f32, 13.0);
641 comptime try testSqrt(f32, 13.0);
642 try testSqrt(f16, 13.0);
643 comptime try testSqrt(f16, 13.0);
644
645 const x = 14.0;
646 const y = x * x;
647 const z = @sqrt(y);
648 comptime try expect(z == x);
649}
650
651fn testSqrt(comptime T: type, x: T) !void {
652 try expect(@sqrt(x * x) == x);
653}
654
655test "@fabs" {
656 try testFabs(f128, 12.0);
657 comptime try testFabs(f128, 12.0);
658 try testFabs(f64, 12.0);
659 comptime try testFabs(f64, 12.0);
660 try testFabs(f32, 12.0);
661 comptime try testFabs(f32, 12.0);
662 try testFabs(f16, 12.0);
663 comptime try testFabs(f16, 12.0);
664
665 const x = 14.0;
666 const y = -x;
667 const z = @fabs(y);
668 comptime try expectEqual(x, z);
669}
670
671fn testFabs(comptime T: type, x: T) !void {
672 const y = -x;
673 const z = @fabs(y);
674 try expectEqual(x, z);
675}
676
677test "@floor" {
678 // FIXME: Generates a floorl function call
679 // testFloor(f128, 12.0);
680 comptime try testFloor(f128, 12.0);
681 try testFloor(f64, 12.0);
682 comptime try testFloor(f64, 12.0);
683 try testFloor(f32, 12.0);
684 comptime try testFloor(f32, 12.0);
685 try testFloor(f16, 12.0);
686 comptime try testFloor(f16, 12.0);
687
688 const x = 14.0;
689 const y = x + 0.7;
690 const z = @floor(y);
691 comptime try expectEqual(x, z);
692}
693
694fn testFloor(comptime T: type, x: T) !void {
695 const y = x + 0.6;
696 const z = @floor(y);
697 try expectEqual(x, z);
698}
699
700test "@ceil" {
701 // FIXME: Generates a ceill function call
702 //testCeil(f128, 12.0);
703 comptime try testCeil(f128, 12.0);
704 try testCeil(f64, 12.0);
705 comptime try testCeil(f64, 12.0);
706 try testCeil(f32, 12.0);
707 comptime try testCeil(f32, 12.0);
708 try testCeil(f16, 12.0);
709 comptime try testCeil(f16, 12.0);
710
711 const x = 14.0;
712 const y = x - 0.7;
713 const z = @ceil(y);
714 comptime try expectEqual(x, z);
715}
716
717fn testCeil(comptime T: type, x: T) !void {
718 const y = x - 0.8;
719 const z = @ceil(y);
720 try expectEqual(x, z);
721}
722
723test "@trunc" {
724 // FIXME: Generates a truncl function call
725 //testTrunc(f128, 12.0);
726 comptime try testTrunc(f128, 12.0);
727 try testTrunc(f64, 12.0);
728 comptime try testTrunc(f64, 12.0);
729 try testTrunc(f32, 12.0);
730 comptime try testTrunc(f32, 12.0);
731 try testTrunc(f16, 12.0);
732 comptime try testTrunc(f16, 12.0);
733
734 const x = 14.0;
735 const y = x + 0.7;
736 const z = @trunc(y);
737 comptime try expectEqual(x, z);
738}
739
740fn testTrunc(comptime T: type, x: T) !void {
741 {
742 const y = x + 0.8;
743 const z = @trunc(y);
744 try expectEqual(x, z);
745 }
746
747 {
748 const y = -x - 0.8;
749 const z = @trunc(y);
750 try expectEqual(-x, z);
751 }
752}
753
754test "@round" {
755 // FIXME: Generates a roundl function call
756 //testRound(f128, 12.0);
757 comptime try testRound(f128, 12.0);
758 try testRound(f64, 12.0);
759 comptime try testRound(f64, 12.0);
760 try testRound(f32, 12.0);
761 comptime try testRound(f32, 12.0);
762 try testRound(f16, 12.0);
763 comptime try testRound(f16, 12.0);
764
765 const x = 14.0;
766 const y = x + 0.4;
767 const z = @round(y);
768 comptime try expectEqual(x, z);
769}
770
771fn testRound(comptime T: type, x: T) !void {
772 const y = x - 0.5;
773 const z = @round(y);
774 try expectEqual(x, z);
775}
776
777test "comptime_int param and return" {
778 const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
779 try expect(a == 137114567242441932203689521744947848950);
780
781 const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
782 try expect(b == 985095453608931032642182098849559179469148836107390954364380);
783}
784
785fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
786 return a + b;
787}
788
789test "vector integer addition" {
790 const S = struct {
791 fn doTheTest() !void {
792 var a: std.meta.Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };
793 var b: std.meta.Vector(4, i32) = [_]i32{ 5, 6, 7, 8 };
794 var result = a + b;
795 var result_array: [4]i32 = result;
796 const expected = [_]i32{ 6, 8, 10, 12 };
797 try expectEqualSlices(i32, &expected, &result_array);
798 }
799 };
800 try S.doTheTest();
801 comptime try S.doTheTest();
802}
803
804test "NaN comparison" {
805 try testNanEqNan(f16);
806 try testNanEqNan(f32);
807 try testNanEqNan(f64);
808 try testNanEqNan(f128);
809 comptime try testNanEqNan(f16);
810 comptime try testNanEqNan(f32);
811 comptime try testNanEqNan(f64);
812 comptime try testNanEqNan(f128);
813}
814
815fn testNanEqNan(comptime F: type) !void {
816 var nan1 = std.math.nan(F);
817 var nan2 = std.math.nan(F);
818 try expect(nan1 != nan2);
819 try expect(!(nan1 == nan2));
820 try expect(!(nan1 > nan2));
821 try expect(!(nan1 >= nan2));
822 try expect(!(nan1 < nan2));
823 try expect(!(nan1 <= nan2));
824}
825
826test "128-bit multiplication" {
827 var a: i128 = 3;
828 var b: i128 = 2;
829 var c = a * b;
830 try expect(c == 6);
831}
832
833test "vector comparison" {
834 const S = struct {
835 fn doTheTest() !void {
836 var a: std.meta.Vector(6, i32) = [_]i32{ 1, 3, -1, 5, 7, 9 };
837 var b: std.meta.Vector(6, i32) = [_]i32{ -1, 3, 0, 6, 10, -10 };
838 try expect(mem.eql(bool, &@as([6]bool, a < b), &[_]bool{ false, false, true, true, true, false }));
839 try expect(mem.eql(bool, &@as([6]bool, a <= b), &[_]bool{ false, true, true, true, true, false }));
840 try expect(mem.eql(bool, &@as([6]bool, a == b), &[_]bool{ false, true, false, false, false, false }));
841 try expect(mem.eql(bool, &@as([6]bool, a != b), &[_]bool{ true, false, true, true, true, true }));
842 try expect(mem.eql(bool, &@as([6]bool, a > b), &[_]bool{ true, false, false, false, false, true }));
843 try expect(mem.eql(bool, &@as([6]bool, a >= b), &[_]bool{ true, true, false, false, false, true }));
844 }
845 };
846 try S.doTheTest();
847 comptime try S.doTheTest();
848}
849
850test "compare undefined literal with comptime_int" {
851 var x = undefined == 1;
852 // x is now undefined with type bool
853 x = true;
854 try expect(x);
855}
856
857test "signed zeros are represented properly" {
858 const S = struct {
859 fn doTheTest() !void {
860 inline for ([_]type{ f16, f32, f64, f128 }) |T| {
861 const ST = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
862 var as_fp_val = -@as(T, 0.0);
863 var as_uint_val = @bitCast(ST, as_fp_val);
864 // Ensure the sign bit is set.
865 try expect(as_uint_val >> (@typeInfo(T).Float.bits - 1) == 1);
866 }
867 }
868 };
869
870 try S.doTheTest();
871 comptime try S.doTheTest();
872}
test/stage1/behavior/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/stage1/behavior/misc.zig deleted-761
...@@ -1,761 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
4const mem = std.mem;
5const builtin = @import("builtin");
6
7// normal comment
8
9/// this is a documentation comment
10/// doc comment line 2
11fn emptyFunctionWithComments() void {}
12
13test "empty function with comments" {
14 emptyFunctionWithComments();
15}
16
17comptime {
18 @export(disabledExternFn, .{ .name = "disabledExternFn", .linkage = .Internal });
19}
20
21fn disabledExternFn() callconv(.C) void {}
22
23test "call disabled extern fn" {
24 disabledExternFn();
25}
26
27test "short circuit" {
28 try testShortCircuit(false, true);
29 comptime try testShortCircuit(false, true);
30}
31
32fn testShortCircuit(f: bool, t: bool) !void {
33 var hit_1 = f;
34 var hit_2 = f;
35 var hit_3 = f;
36 var hit_4 = f;
37
38 if (t or x: {
39 try expect(f);
40 break :x f;
41 }) {
42 hit_1 = t;
43 }
44 if (f or x: {
45 hit_2 = t;
46 break :x f;
47 }) {
48 try expect(f);
49 }
50
51 if (t and x: {
52 hit_3 = t;
53 break :x f;
54 }) {
55 try expect(f);
56 }
57 if (f and x: {
58 try expect(f);
59 break :x f;
60 }) {
61 try expect(f);
62 } else {
63 hit_4 = t;
64 }
65 try expect(hit_1);
66 try expect(hit_2);
67 try expect(hit_3);
68 try expect(hit_4);
69}
70
71test "truncate" {
72 try expect(testTruncate(0x10fd) == 0xfd);
73}
74fn testTruncate(x: u32) u8 {
75 return @truncate(u8, x);
76}
77
78fn first4KeysOfHomeRow() []const u8 {
79 return "aoeu";
80}
81
82test "return string from function" {
83 try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
84}
85
86const g1: i32 = 1233 + 1;
87var g2: i32 = 0;
88
89test "global variables" {
90 try expect(g2 == 0);
91 g2 = g1;
92 try expect(g2 == 1234);
93}
94
95test "memcpy and memset intrinsics" {
96 var foo: [20]u8 = undefined;
97 var bar: [20]u8 = undefined;
98
99 @memset(&foo, 'A', foo.len);
100 @memcpy(&bar, &foo, bar.len);
101
102 if (bar[11] != 'A') unreachable;
103}
104
105test "builtin static eval" {
106 const x: i32 = comptime x: {
107 break :x 1 + 2 + 3;
108 };
109 try expect(x == comptime 6);
110}
111
112test "slicing" {
113 var array: [20]i32 = undefined;
114
115 array[5] = 1234;
116
117 var slice = array[5..10];
118
119 if (slice.len != 5) unreachable;
120
121 const ptr = &slice[0];
122 if (ptr.* != 1234) unreachable;
123
124 var slice_rest = array[10..];
125 if (slice_rest.len != 10) unreachable;
126}
127
128test "constant equal function pointers" {
129 const alias = emptyFn;
130 try expect(comptime x: {
131 break :x emptyFn == alias;
132 });
133}
134
135fn emptyFn() void {}
136
137test "hex escape" {
138 try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
139}
140
141test "string concatenation" {
142 try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
143}
144
145test "array mult operator" {
146 try expect(mem.eql(u8, "ab" ** 5, "ababababab"));
147}
148
149test "string escapes" {
150 try expect(mem.eql(u8, "\"", "\x22"));
151 try expect(mem.eql(u8, "\'", "\x27"));
152 try expect(mem.eql(u8, "\n", "\x0a"));
153 try expect(mem.eql(u8, "\r", "\x0d"));
154 try expect(mem.eql(u8, "\t", "\x09"));
155 try expect(mem.eql(u8, "\\", "\x5c"));
156 try expect(mem.eql(u8, "\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01"));
157}
158
159test "multiline string" {
160 const s1 =
161 \\one
162 \\two)
163 \\three
164 ;
165 const s2 = "one\ntwo)\nthree";
166 try expect(mem.eql(u8, s1, s2));
167}
168
169test "multiline string comments at start" {
170 const s1 =
171 //\\one
172 \\two)
173 \\three
174 ;
175 const s2 = "two)\nthree";
176 try expect(mem.eql(u8, s1, s2));
177}
178
179test "multiline string comments at end" {
180 const s1 =
181 \\one
182 \\two)
183 //\\three
184 ;
185 const s2 = "one\ntwo)";
186 try expect(mem.eql(u8, s1, s2));
187}
188
189test "multiline string comments in middle" {
190 const s1 =
191 \\one
192 //\\two)
193 \\three
194 ;
195 const s2 = "one\nthree";
196 try expect(mem.eql(u8, s1, s2));
197}
198
199test "multiline string comments at multiple places" {
200 const s1 =
201 \\one
202 //\\two
203 \\three
204 //\\four
205 \\five
206 ;
207 const s2 = "one\nthree\nfive";
208 try expect(mem.eql(u8, s1, s2));
209}
210
211test "multiline C string" {
212 const s1 =
213 \\one
214 \\two)
215 \\three
216 ;
217 const s2 = "one\ntwo)\nthree";
218 try expect(std.cstr.cmp(s1, s2) == 0);
219}
220
221test "type equality" {
222 try expect(*const u8 != *u8);
223}
224
225const global_a: i32 = 1234;
226const global_b: *const i32 = &global_a;
227const global_c: *const f32 = @ptrCast(*const f32, global_b);
228test "compile time global reinterpret" {
229 const d = @ptrCast(*const i32, global_c);
230 try expect(d.* == 1234);
231}
232
233test "explicit cast maybe pointers" {
234 const a: ?*i32 = undefined;
235 const b: ?*f32 = @ptrCast(?*f32, a);
236}
237
238test "generic malloc free" {
239 const a = memAlloc(u8, 10) catch unreachable;
240 memFree(u8, a);
241}
242var some_mem: [100]u8 = undefined;
243fn memAlloc(comptime T: type, n: usize) anyerror![]T {
244 return @ptrCast([*]T, &some_mem[0])[0..n];
245}
246fn memFree(comptime T: type, memory: []T) void {}
247
248test "cast undefined" {
249 const array: [100]u8 = undefined;
250 const slice = @as([]const u8, &array);
251 testCastUndefined(slice);
252}
253fn testCastUndefined(x: []const u8) void {}
254
255test "cast small unsigned to larger signed" {
256 try expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200));
257 try expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999));
258}
259fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
260 return x;
261}
262fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
263 return x;
264}
265
266test "implicit cast after unreachable" {
267 try expect(outer() == 1234);
268}
269fn inner() i32 {
270 return 1234;
271}
272fn outer() i64 {
273 return inner();
274}
275
276test "pointer dereferencing" {
277 var x = @as(i32, 3);
278 const y = &x;
279
280 y.* += 1;
281
282 try expect(x == 4);
283 try expect(y.* == 4);
284}
285
286test "call result of if else expression" {
287 try expect(mem.eql(u8, f2(true), "a"));
288 try expect(mem.eql(u8, f2(false), "b"));
289}
290fn f2(x: bool) []const u8 {
291 return (if (x) fA else fB)();
292}
293fn fA() []const u8 {
294 return "a";
295}
296fn fB() []const u8 {
297 return "b";
298}
299
300test "const expression eval handling of variables" {
301 var x = true;
302 while (x) {
303 x = false;
304 }
305}
306
307test "constant enum initialization with differing sizes" {
308 try test3_1(test3_foo);
309 try test3_2(test3_bar);
310}
311const Test3Foo = union(enum) {
312 One: void,
313 Two: f32,
314 Three: Test3Point,
315};
316const Test3Point = struct {
317 x: i32,
318 y: i32,
319};
320const test3_foo = Test3Foo{
321 .Three = Test3Point{
322 .x = 3,
323 .y = 4,
324 },
325};
326const test3_bar = Test3Foo{ .Two = 13 };
327fn test3_1(f: Test3Foo) !void {
328 switch (f) {
329 Test3Foo.Three => |pt| {
330 try expect(pt.x == 3);
331 try expect(pt.y == 4);
332 },
333 else => unreachable,
334 }
335}
336fn test3_2(f: Test3Foo) !void {
337 switch (f) {
338 Test3Foo.Two => |x| {
339 try expect(x == 13);
340 },
341 else => unreachable,
342 }
343}
344
345test "character literals" {
346 try expect('\'' == single_quote);
347}
348const single_quote = '\'';
349
350test "take address of parameter" {
351 try testTakeAddressOfParameter(12.34);
352}
353fn testTakeAddressOfParameter(f: f32) !void {
354 const f_ptr = &f;
355 try expect(f_ptr.* == 12.34);
356}
357
358test "pointer comparison" {
359 const a = @as([]const u8, "a");
360 const b = &a;
361 try expect(ptrEql(b, b));
362}
363fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
364 return a == b;
365}
366
367test "string concatenation" {
368 const a = "OK" ++ " IT " ++ "WORKED";
369 const b = "OK IT WORKED";
370
371 comptime try expect(@TypeOf(a) == *const [12:0]u8);
372 comptime try expect(@TypeOf(b) == *const [12:0]u8);
373
374 const len = mem.len(b);
375 const len_with_null = len + 1;
376 {
377 var i: u32 = 0;
378 while (i < len_with_null) : (i += 1) {
379 try expect(a[i] == b[i]);
380 }
381 }
382 try expect(a[len] == 0);
383 try expect(b[len] == 0);
384}
385
386test "pointer to void return type" {
387 testPointerToVoidReturnType() catch unreachable;
388}
389fn testPointerToVoidReturnType() anyerror!void {
390 const a = testPointerToVoidReturnType2();
391 return a.*;
392}
393const test_pointer_to_void_return_type_x = void{};
394fn testPointerToVoidReturnType2() *const void {
395 return &test_pointer_to_void_return_type_x;
396}
397
398test "non const ptr to aliased type" {
399 const int = i32;
400 try expect(?*int == ?*i32);
401}
402
403test "array 2D const double ptr" {
404 const rect_2d_vertexes = [_][1]f32{
405 [_]f32{1.0},
406 [_]f32{2.0},
407 };
408 try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
409}
410
411fn testArray2DConstDoublePtr(ptr: *const f32) !void {
412 const ptr2 = @ptrCast([*]const f32, ptr);
413 try expect(ptr2[0] == 1.0);
414 try expect(ptr2[1] == 2.0);
415}
416
417const AStruct = struct {
418 x: i32,
419};
420const AnEnum = enum {
421 One,
422 Two,
423};
424const AUnionEnum = union(enum) {
425 One: i32,
426 Two: void,
427};
428const AUnion = union {
429 One: void,
430 Two: void,
431};
432
433test "@typeName" {
434 const Struct = struct {};
435 const Union = union {
436 unused: u8,
437 };
438 const Enum = enum {
439 Unused,
440 };
441 comptime {
442 try expect(mem.eql(u8, @typeName(i64), "i64"));
443 try expect(mem.eql(u8, @typeName(*usize), "*usize"));
444 // https://github.com/ziglang/zig/issues/675
445 try expect(mem.eql(u8, "behavior.misc.TypeFromFn(u8)", @typeName(TypeFromFn(u8))));
446 try expect(mem.eql(u8, @typeName(Struct), "Struct"));
447 try expect(mem.eql(u8, @typeName(Union), "Union"));
448 try expect(mem.eql(u8, @typeName(Enum), "Enum"));
449 }
450}
451
452fn TypeFromFn(comptime T: type) type {
453 return struct {};
454}
455
456test "double implicit cast in same expression" {
457 var x = @as(i32, @as(u16, nine()));
458 try expect(x == 9);
459}
460fn nine() u8 {
461 return 9;
462}
463
464test "global variable initialized to global variable array element" {
465 try expect(global_ptr == &gdt[0]);
466}
467const GDTEntry = struct {
468 field: i32,
469};
470var gdt = [_]GDTEntry{
471 GDTEntry{ .field = 1 },
472 GDTEntry{ .field = 2 },
473};
474var global_ptr = &gdt[0];
475
476// can't really run this test but we can make sure it has no compile error
477// and generates code
478const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
479export fn writeToVRam() void {
480 vram[0] = 'X';
481}
482
483const OpaqueA = opaque {};
484const OpaqueB = opaque {};
485test "opaque types" {
486 try expect(*OpaqueA != *OpaqueB);
487 try expect(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
488 try expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
489}
490
491test "variable is allowed to be a pointer to an opaque type" {
492 var x: i32 = 1234;
493 _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
494}
495fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
496 var a = ptr;
497 return a;
498}
499
500test "comptime if inside runtime while which unconditionally breaks" {
501 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
502 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
503}
504fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
505 while (cond) {
506 if (false) {}
507 break;
508 }
509}
510
511test "implicit comptime while" {
512 while (false) {
513 @compileError("bad");
514 }
515}
516
517fn fnThatClosesOverLocalConst() type {
518 const c = 1;
519 return struct {
520 fn g() i32 {
521 return c;
522 }
523 };
524}
525
526test "function closes over local const" {
527 const x = fnThatClosesOverLocalConst().g();
528 try expect(x == 1);
529}
530
531test "cold function" {
532 thisIsAColdFn();
533 comptime thisIsAColdFn();
534}
535
536fn thisIsAColdFn() void {
537 @setCold(true);
538}
539
540const PackedStruct = packed struct {
541 a: u8,
542 b: u8,
543};
544const PackedUnion = packed union {
545 a: u8,
546 b: u32,
547};
548const PackedEnum = packed enum {
549 A,
550 B,
551};
552
553test "packed struct, enum, union parameters in extern function" {
554 testPackedStuff(&(PackedStruct{
555 .a = 1,
556 .b = 2,
557 }), &(PackedUnion{ .a = 1 }), PackedEnum.A);
558}
559
560export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {}
561
562test "slicing zero length array" {
563 const s1 = ""[0..];
564 const s2 = ([_]u32{})[0..];
565 try expect(s1.len == 0);
566 try expect(s2.len == 0);
567 try expect(mem.eql(u8, s1, ""));
568 try expect(mem.eql(u32, s2, &[_]u32{}));
569}
570
571const addr1 = @ptrCast(*const u8, emptyFn);
572test "comptime cast fn to ptr" {
573 const addr2 = @ptrCast(*const u8, emptyFn);
574 comptime try expect(addr1 == addr2);
575}
576
577test "equality compare fn ptrs" {
578 var a = emptyFn;
579 try expect(a == a);
580}
581
582test "self reference through fn ptr field" {
583 const S = struct {
584 const A = struct {
585 f: fn (A) u8,
586 };
587
588 fn foo(a: A) u8 {
589 return 12;
590 }
591 };
592 var a: S.A = undefined;
593 a.f = S.foo;
594 try expect(a.f(a) == 12);
595}
596
597test "volatile load and store" {
598 var number: i32 = 1234;
599 const ptr = @as(*volatile i32, &number);
600 ptr.* += 1;
601 try expect(ptr.* == 1235);
602}
603
604test "slice string literal has correct type" {
605 comptime {
606 try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
607 const array = [_]i32{ 1, 2, 3, 4 };
608 try expect(@TypeOf(array[0..]) == *const [4]i32);
609 }
610 var runtime_zero: usize = 0;
611 comptime try expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);
612 const array = [_]i32{ 1, 2, 3, 4 };
613 comptime try expect(@TypeOf(array[runtime_zero..]) == []const i32);
614}
615
616test "struct inside function" {
617 try testStructInFn();
618 comptime try testStructInFn();
619}
620
621fn testStructInFn() !void {
622 const BlockKind = u32;
623
624 const Block = struct {
625 kind: BlockKind,
626 };
627
628 var block = Block{ .kind = 1234 };
629
630 block.kind += 1;
631
632 try expect(block.kind == 1235);
633}
634
635test "fn call returning scalar optional in equality expression" {
636 try expect(getNull() == null);
637}
638
639fn getNull() ?*i32 {
640 return null;
641}
642
643test "thread local variable" {
644 const S = struct {
645 threadlocal var t: i32 = 1234;
646 };
647 S.t += 1;
648 try expect(S.t == 1235);
649}
650
651test "unicode escape in character literal" {
652 var a: u24 = '\u{01f4a9}';
653 try expect(a == 128169);
654}
655
656test "unicode character in character literal" {
657 try expect('💩' == 128169);
658}
659
660test "result location zero sized array inside struct field implicit cast to slice" {
661 const E = struct {
662 entries: []u32,
663 };
664 var foo = E{ .entries = &[_]u32{} };
665 try expect(foo.entries.len == 0);
666}
667
668var global_foo: *i32 = undefined;
669
670test "global variable assignment with optional unwrapping with var initialized to undefined" {
671 const S = struct {
672 var data: i32 = 1234;
673 fn foo() ?*i32 {
674 return &data;
675 }
676 };
677 global_foo = S.foo() orelse {
678 @panic("bad");
679 };
680 try expect(global_foo.* == 1234);
681}
682
683test "peer result location with typed parent, runtime condition, comptime prongs" {
684 const S = struct {
685 fn doTheTest(arg: i32) i32 {
686 const st = Structy{
687 .bleh = if (arg == 1) 1 else 1,
688 };
689
690 if (st.bleh == 1)
691 return 1234;
692 return 0;
693 }
694
695 const Structy = struct {
696 bleh: i32,
697 };
698 };
699 try expect(S.doTheTest(0) == 1234);
700 try expect(S.doTheTest(1) == 1234);
701}
702
703test "nested optional field in struct" {
704 const S2 = struct {
705 y: u8,
706 };
707 const S1 = struct {
708 x: ?S2,
709 };
710 var s = S1{
711 .x = S2{ .y = 127 },
712 };
713 try expect(s.x.?.y == 127);
714}
715
716fn maybe(x: bool) anyerror!?u32 {
717 return switch (x) {
718 true => @as(u32, 42),
719 else => null,
720 };
721}
722
723test "result location is optional inside error union" {
724 const x = maybe(true) catch unreachable;
725 try expect(x.? == 42);
726}
727
728threadlocal var buffer: [11]u8 = undefined;
729
730test "pointer to thread local array" {
731 const s = "Hello world";
732 std.mem.copy(u8, buffer[0..], s);
733 try std.testing.expectEqualSlices(u8, buffer[0..], s);
734}
735
736test "auto created variables have correct alignment" {
737 const S = struct {
738 fn foo(str: [*]const u8) u32 {
739 for (@ptrCast([*]align(1) const u32, str)[0..1]) |v| {
740 return v;
741 }
742 return 0;
743 }
744 };
745 try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
746 comptime try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
747}
748
749extern var opaque_extern_var: opaque {};
750var var_to_export: u32 = 42;
751test "extern variable with non-pointer opaque type" {
752 @export(var_to_export, .{ .name = "opaque_extern_var" });
753 try expect(@ptrCast(*align(1) u32, &opaque_extern_var).* == 42);
754}
755
756test "lazy typeInfo value as generic parameter" {
757 const S = struct {
758 fn foo(args: anytype) void {}
759 };
760 S.foo(@typeInfo(@TypeOf(.{})));
761}
test/stage1/behavior/muladd.zig deleted-34
...@@ -1,34 +0,0 @@
1const expect = @import("std").testing.expect;
2
3test "@mulAdd" {
4 comptime try testMulAdd();
5 try testMulAdd();
6}
7
8fn testMulAdd() !void {
9 {
10 var a: f16 = 5.5;
11 var b: f16 = 2.5;
12 var c: f16 = 6.25;
13 try expect(@mulAdd(f16, a, b, c) == 20);
14 }
15 {
16 var a: f32 = 5.5;
17 var b: f32 = 2.5;
18 var c: f32 = 6.25;
19 try expect(@mulAdd(f32, a, b, c) == 20);
20 }
21 {
22 var a: f64 = 5.5;
23 var b: f64 = 2.5;
24 var c: f64 = 6.25;
25 try expect(@mulAdd(f64, a, b, c) == 20);
26 }
27 // Awaits implementation in libm.zig
28 //{
29 // var a: f16 = 5.5;
30 // var b: f128 = 2.5;
31 // var c: f128 = 6.25;
32 //try expect(@mulAdd(f128, a, b, c) == 20);
33 //}
34}
test/stage1/behavior/namespace_depends_on_compile_var.zig deleted-14
...@@ -1,14 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "namespace depends on compile var" {
5 if (some_namespace.a_bool) {
6 try expect(some_namespace.a_bool);
7 } else {
8 try expect(!some_namespace.a_bool);
9 }
10}
11const some_namespace = switch (std.builtin.os.tag) {
12 .linux => @import("namespace_depends_on_compile_var/a.zig"),
13 else => @import("namespace_depends_on_compile_var/b.zig"),
14};
test/stage1/behavior/namespace_depends_on_compile_var/a.zig deleted-1
...@@ -1 +0,0 @@
1pub const a_bool = true;
test/stage1/behavior/namespace_depends_on_compile_var/b.zig deleted-1
...@@ -1 +0,0 @@
1pub const a_bool = false;
test/stage1/behavior/null.zig deleted-162
...@@ -1,162 +0,0 @@
1const expect = @import("std").testing.expect;
2
3test "optional type" {
4 const x: ?bool = true;
5
6 if (x) |y| {
7 if (y) {
8 // OK
9 } else {
10 unreachable;
11 }
12 } else {
13 unreachable;
14 }
15
16 const next_x: ?i32 = null;
17
18 const z = next_x orelse 1234;
19
20 try expect(z == 1234);
21
22 const final_x: ?i32 = 13;
23
24 const num = final_x orelse unreachable;
25
26 try expect(num == 13);
27}
28
29test "test maybe object and get a pointer to the inner value" {
30 var maybe_bool: ?bool = true;
31
32 if (maybe_bool) |*b| {
33 b.* = false;
34 }
35
36 try expect(maybe_bool.? == false);
37}
38
39test "rhs maybe unwrap return" {
40 const x: ?bool = true;
41 const y = x orelse return;
42}
43
44test "maybe return" {
45 try maybeReturnImpl();
46 comptime try maybeReturnImpl();
47}
48
49fn maybeReturnImpl() !void {
50 try expect(foo(1235).?);
51 if (foo(null) != null) unreachable;
52 try expect(!foo(1234).?);
53}
54
55fn foo(x: ?i32) ?bool {
56 const value = x orelse return null;
57 return value > 1234;
58}
59
60test "if var maybe pointer" {
61 try expect(shouldBeAPlus1(Particle{
62 .a = 14,
63 .b = 1,
64 .c = 1,
65 .d = 1,
66 }) == 15);
67}
68fn shouldBeAPlus1(p: Particle) u64 {
69 var maybe_particle: ?Particle = p;
70 if (maybe_particle) |*particle| {
71 particle.a += 1;
72 }
73 if (maybe_particle) |particle| {
74 return particle.a;
75 }
76 return 0;
77}
78const Particle = struct {
79 a: u64,
80 b: u64,
81 c: u64,
82 d: u64,
83};
84
85test "null literal outside function" {
86 const is_null = here_is_a_null_literal.context == null;
87 try expect(is_null);
88
89 const is_non_null = here_is_a_null_literal.context != null;
90 try expect(!is_non_null);
91}
92const SillyStruct = struct {
93 context: ?i32,
94};
95const here_is_a_null_literal = SillyStruct{ .context = null };
96
97test "test null runtime" {
98 try testTestNullRuntime(null);
99}
100fn testTestNullRuntime(x: ?i32) !void {
101 try expect(x == null);
102 try expect(!(x != null));
103}
104
105test "optional void" {
106 try optionalVoidImpl();
107 comptime try optionalVoidImpl();
108}
109
110fn optionalVoidImpl() !void {
111 try expect(bar(null) == null);
112 try expect(bar({}) != null);
113}
114
115fn bar(x: ?void) ?void {
116 if (x) |_| {
117 return {};
118 } else {
119 return null;
120 }
121}
122
123const StructWithOptional = struct {
124 field: ?i32,
125};
126
127var struct_with_optional: StructWithOptional = undefined;
128
129test "unwrap optional which is field of global var" {
130 struct_with_optional.field = null;
131 if (struct_with_optional.field) |payload| {
132 unreachable;
133 }
134 struct_with_optional.field = 1234;
135 if (struct_with_optional.field) |payload| {
136 try expect(payload == 1234);
137 } else {
138 unreachable;
139 }
140}
141
142test "null with default unwrap" {
143 const x: i32 = null orelse 1;
144 try expect(x == 1);
145}
146
147test "optional types" {
148 comptime {
149 const opt_type_struct = StructWithOptionalType{ .t = u8 };
150 try expect(opt_type_struct.t != null and opt_type_struct.t.? == u8);
151 }
152}
153
154const StructWithOptionalType = struct {
155 t: ?type,
156};
157
158test "optional pointer to 0 bit type null value at runtime" {
159 const EmptyStruct = struct {};
160 var x: ?*EmptyStruct = null;
161 try expect(x == null);
162}
test/stage1/behavior/optional.zig deleted-269
...@@ -1,269 +0,0 @@
1const std = @import("std");
2const testing = std.testing;
3const expect = testing.expect;
4const expectEqual = testing.expectEqual;
5
6pub const EmptyStruct = struct {};
7
8test "optional pointer to size zero struct" {
9 var e = EmptyStruct{};
10 var o: ?*EmptyStruct = &e;
11 try expect(o != null);
12}
13
14test "equality compare nullable pointers" {
15 try testNullPtrsEql();
16 comptime try testNullPtrsEql();
17}
18
19fn testNullPtrsEql() !void {
20 var number: i32 = 1234;
21
22 var x: ?*i32 = null;
23 var y: ?*i32 = null;
24 try expect(x == y);
25 y = &number;
26 try expect(x != y);
27 try expect(x != &number);
28 try expect(&number != x);
29 x = &number;
30 try expect(x == y);
31 try expect(x == &number);
32 try expect(&number == x);
33}
34
35test "address of unwrap optional" {
36 const S = struct {
37 const Foo = struct {
38 a: i32,
39 };
40
41 var global: ?Foo = null;
42
43 pub fn getFoo() anyerror!*Foo {
44 return &global.?;
45 }
46 };
47 S.global = S.Foo{ .a = 1234 };
48 const foo = S.getFoo() catch unreachable;
49 try expect(foo.a == 1234);
50}
51
52test "equality compare optional with non-optional" {
53 try test_cmp_optional_non_optional();
54 comptime try test_cmp_optional_non_optional();
55}
56
57fn test_cmp_optional_non_optional() !void {
58 var ten: i32 = 10;
59 var opt_ten: ?i32 = 10;
60 var five: i32 = 5;
61 var int_n: ?i32 = null;
62
63 try expect(int_n != ten);
64 try expect(opt_ten == ten);
65 try expect(opt_ten != five);
66
67 // test evaluation is always lexical
68 // ensure that the optional isn't always computed before the non-optional
69 var mutable_state: i32 = 0;
70 _ = blk1: {
71 mutable_state += 1;
72 break :blk1 @as(?f64, 10.0);
73 } != blk2: {
74 try expect(mutable_state == 1);
75 break :blk2 @as(f64, 5.0);
76 };
77 _ = blk1: {
78 mutable_state += 1;
79 break :blk1 @as(f64, 10.0);
80 } != blk2: {
81 try expect(mutable_state == 2);
82 break :blk2 @as(?f64, 5.0);
83 };
84}
85
86test "passing an optional integer as a parameter" {
87 const S = struct {
88 fn entry() bool {
89 var x: i32 = 1234;
90 return foo(x);
91 }
92
93 fn foo(x: ?i32) bool {
94 return x.? == 1234;
95 }
96 };
97 try expect(S.entry());
98 comptime try expect(S.entry());
99}
100
101test "unwrap function call with optional pointer return value" {
102 const S = struct {
103 fn entry() !void {
104 try expect(foo().?.* == 1234);
105 try expect(bar() == null);
106 }
107 const global: i32 = 1234;
108 fn foo() ?*const i32 {
109 return &global;
110 }
111 fn bar() ?*i32 {
112 return null;
113 }
114 };
115 try S.entry();
116 comptime try S.entry();
117}
118
119test "nested orelse" {
120 const S = struct {
121 fn entry() !void {
122 try expect(func() == null);
123 }
124 fn maybe() ?Foo {
125 return null;
126 }
127 fn func() ?Foo {
128 const x = maybe() orelse
129 maybe() orelse
130 return null;
131 unreachable;
132 }
133 const Foo = struct {
134 field: i32,
135 };
136 };
137 try S.entry();
138 comptime try S.entry();
139}
140
141test "self-referential struct through a slice of optional" {
142 const S = struct {
143 const Node = struct {
144 children: []?Node,
145 data: ?u8,
146
147 fn new() Node {
148 return Node{
149 .children = undefined,
150 .data = null,
151 };
152 }
153 };
154 };
155
156 var n = S.Node.new();
157 try expect(n.data == null);
158}
159
160test "assigning to an unwrapped optional field in an inline loop" {
161 comptime var maybe_pos_arg: ?comptime_int = null;
162 inline for ("ab") |x| {
163 maybe_pos_arg = 0;
164 if (maybe_pos_arg.? != 0) {
165 @compileError("bad");
166 }
167 maybe_pos_arg.? = 10;
168 }
169}
170
171test "coerce an anon struct literal to optional struct" {
172 const S = struct {
173 const Struct = struct {
174 field: u32,
175 };
176 fn doTheTest() !void {
177 var maybe_dims: ?Struct = null;
178 maybe_dims = .{ .field = 1 };
179 try expect(maybe_dims.?.field == 1);
180 }
181 };
182 try S.doTheTest();
183 comptime try S.doTheTest();
184}
185
186test "optional with void type" {
187 const Foo = struct {
188 x: ?void,
189 };
190 var x = Foo{ .x = null };
191 try expect(x.x == null);
192}
193
194test "0-bit child type coerced to optional return ptr result location" {
195 const S = struct {
196 fn doTheTest() !void {
197 var y = Foo{};
198 var z = y.thing();
199 try expect(z != null);
200 }
201
202 const Foo = struct {
203 pub const Bar = struct {
204 field: *Foo,
205 };
206
207 pub fn thing(self: *Foo) ?Bar {
208 return Bar{ .field = self };
209 }
210 };
211 };
212 try S.doTheTest();
213 comptime try S.doTheTest();
214}
215
216test "0-bit child type coerced to optional" {
217 const S = struct {
218 fn doTheTest() !void {
219 var it: Foo = .{
220 .list = undefined,
221 };
222 try expect(it.foo() != null);
223 }
224
225 const Empty = struct {};
226 const Foo = struct {
227 list: [10]Empty,
228
229 fn foo(self: *Foo) ?*Empty {
230 const data = &self.list[0];
231 return data;
232 }
233 };
234 };
235 try S.doTheTest();
236 comptime try S.doTheTest();
237}
238
239test "array of optional unaligned types" {
240 const Enum = enum { one, two, three };
241
242 const SomeUnion = union(enum) {
243 Num: Enum,
244 Other: u32,
245 };
246
247 const values = [_]?SomeUnion{
248 SomeUnion{ .Num = .one },
249 SomeUnion{ .Num = .two },
250 SomeUnion{ .Num = .three },
251 SomeUnion{ .Num = .one },
252 SomeUnion{ .Num = .two },
253 SomeUnion{ .Num = .three },
254 };
255
256 // The index must be a runtime value
257 var i: usize = 0;
258 try expectEqual(Enum.one, values[i].?.Num);
259 i += 1;
260 try expectEqual(Enum.two, values[i].?.Num);
261 i += 1;
262 try expectEqual(Enum.three, values[i].?.Num);
263 i += 1;
264 try expectEqual(Enum.one, values[i].?.Num);
265 i += 1;
266 try expectEqual(Enum.two, values[i].?.Num);
267 i += 1;
268 try expectEqual(Enum.three, values[i].?.Num);
269}
test/stage1/behavior/pointers.zig deleted-339
...@@ -1,339 +0,0 @@
1const std = @import("std");
2const testing = std.testing;
3const expect = testing.expect;
4const expectError = testing.expectError;
5
6test "dereference pointer" {
7 comptime try testDerefPtr();
8 try testDerefPtr();
9}
10
11fn testDerefPtr() !void {
12 var x: i32 = 1234;
13 var y = &x;
14 y.* += 1;
15 try expect(x == 1235);
16}
17
18const Foo1 = struct {
19 x: void,
20};
21
22test "dereference pointer again" {
23 try testDerefPtrOneVal();
24 comptime try testDerefPtrOneVal();
25}
26
27fn testDerefPtrOneVal() !void {
28 // Foo1 satisfies the OnePossibleValueYes criteria
29 const x = &Foo1{ .x = {} };
30 const y = x.*;
31 try expect(@TypeOf(y.x) == void);
32}
33
34test "pointer arithmetic" {
35 var ptr: [*]const u8 = "abcd";
36
37 try expect(ptr[0] == 'a');
38 ptr += 1;
39 try expect(ptr[0] == 'b');
40 ptr += 1;
41 try expect(ptr[0] == 'c');
42 ptr += 1;
43 try expect(ptr[0] == 'd');
44 ptr += 1;
45 try expect(ptr[0] == 0);
46 ptr -= 1;
47 try expect(ptr[0] == 'd');
48 ptr -= 1;
49 try expect(ptr[0] == 'c');
50 ptr -= 1;
51 try expect(ptr[0] == 'b');
52 ptr -= 1;
53 try expect(ptr[0] == 'a');
54}
55
56test "double pointer parsing" {
57 comptime try expect(PtrOf(PtrOf(i32)) == **i32);
58}
59
60fn PtrOf(comptime T: type) type {
61 return *T;
62}
63
64test "assigning integer to C pointer" {
65 var x: i32 = 0;
66 var ptr: [*c]u8 = 0;
67 var ptr2: [*c]u8 = x;
68}
69
70test "implicit cast single item pointer to C pointer and back" {
71 var y: u8 = 11;
72 var x: [*c]u8 = &y;
73 var z: *u8 = x;
74 z.* += 1;
75 try expect(y == 12);
76}
77
78test "C pointer comparison and arithmetic" {
79 const S = struct {
80 fn doTheTest() !void {
81 var one: usize = 1;
82 var ptr1: [*c]u32 = 0;
83 var ptr2 = ptr1 + 10;
84 try expect(ptr1 == 0);
85 try expect(ptr1 >= 0);
86 try expect(ptr1 <= 0);
87 // expect(ptr1 < 1);
88 // expect(ptr1 < one);
89 // expect(1 > ptr1);
90 // expect(one > ptr1);
91 try expect(ptr1 < ptr2);
92 try expect(ptr2 > ptr1);
93 try expect(ptr2 >= 40);
94 try expect(ptr2 == 40);
95 try expect(ptr2 <= 40);
96 ptr2 -= 10;
97 try expect(ptr1 == ptr2);
98 }
99 };
100 try S.doTheTest();
101 comptime try S.doTheTest();
102}
103
104test "peer type resolution with C pointers" {
105 var ptr_one: *u8 = undefined;
106 var ptr_many: [*]u8 = undefined;
107 var ptr_c: [*c]u8 = undefined;
108 var t = true;
109 var x1 = if (t) ptr_one else ptr_c;
110 var x2 = if (t) ptr_many else ptr_c;
111 var x3 = if (t) ptr_c else ptr_one;
112 var x4 = if (t) ptr_c else ptr_many;
113 try expect(@TypeOf(x1) == [*c]u8);
114 try expect(@TypeOf(x2) == [*c]u8);
115 try expect(@TypeOf(x3) == [*c]u8);
116 try expect(@TypeOf(x4) == [*c]u8);
117}
118
119test "implicit casting between C pointer and optional non-C pointer" {
120 var slice: []const u8 = "aoeu";
121 const opt_many_ptr: ?[*]const u8 = slice.ptr;
122 var ptr_opt_many_ptr = &opt_many_ptr;
123 var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
124 try expect(c_ptr.*.* == 'a');
125 ptr_opt_many_ptr = c_ptr;
126 try expect(ptr_opt_many_ptr.*.?[1] == 'o');
127}
128
129test "implicit cast error unions with non-optional to optional pointer" {
130 const S = struct {
131 fn doTheTest() !void {
132 try expectError(error.Fail, foo());
133 }
134 fn foo() anyerror!?*u8 {
135 return bar() orelse error.Fail;
136 }
137 fn bar() ?*u8 {
138 return null;
139 }
140 };
141 try S.doTheTest();
142 comptime try S.doTheTest();
143}
144
145test "initialize const optional C pointer to null" {
146 const a: ?[*c]i32 = null;
147 try expect(a == null);
148 comptime try expect(a == null);
149}
150
151test "compare equality of optional and non-optional pointer" {
152 const a = @intToPtr(*const usize, 0x12345678);
153 const b = @intToPtr(?*usize, 0x12345678);
154 try expect(a == b);
155 try expect(b == a);
156}
157
158test "allowzero pointer and slice" {
159 var ptr = @intToPtr([*]allowzero i32, 0);
160 var opt_ptr: ?[*]allowzero i32 = ptr;
161 try expect(opt_ptr != null);
162 try expect(@ptrToInt(ptr) == 0);
163 var runtime_zero: usize = 0;
164 var slice = ptr[runtime_zero..10];
165 comptime try expect(@TypeOf(slice) == []allowzero i32);
166 try expect(@ptrToInt(&slice[5]) == 20);
167
168 comptime try expect(@typeInfo(@TypeOf(ptr)).Pointer.is_allowzero);
169 comptime try expect(@typeInfo(@TypeOf(slice)).Pointer.is_allowzero);
170}
171
172test "assign null directly to C pointer and test null equality" {
173 var x: [*c]i32 = null;
174 try expect(x == null);
175 try expect(null == x);
176 try expect(!(x != null));
177 try expect(!(null != x));
178 if (x) |same_x| {
179 @panic("fail");
180 }
181 var otherx: i32 = undefined;
182 try expect((x orelse &otherx) == &otherx);
183
184 const y: [*c]i32 = null;
185 comptime try expect(y == null);
186 comptime try expect(null == y);
187 comptime try expect(!(y != null));
188 comptime try expect(!(null != y));
189 if (y) |same_y| @panic("fail");
190 const othery: i32 = undefined;
191 comptime try expect((y orelse &othery) == &othery);
192
193 var n: i32 = 1234;
194 var x1: [*c]i32 = &n;
195 try expect(!(x1 == null));
196 try expect(!(null == x1));
197 try expect(x1 != null);
198 try expect(null != x1);
199 try expect(x1.?.* == 1234);
200 if (x1) |same_x1| {
201 try expect(same_x1.* == 1234);
202 } else {
203 @panic("fail");
204 }
205 try expect((x1 orelse &otherx) == x1);
206
207 const nc: i32 = 1234;
208 const y1: [*c]const i32 = &nc;
209 comptime try expect(!(y1 == null));
210 comptime try expect(!(null == y1));
211 comptime try expect(y1 != null);
212 comptime try expect(null != y1);
213 comptime try expect(y1.?.* == 1234);
214 if (y1) |same_y1| {
215 try expect(same_y1.* == 1234);
216 } else {
217 @compileError("fail");
218 }
219 comptime try expect((y1 orelse &othery) == y1);
220}
221
222test "null terminated pointer" {
223 const S = struct {
224 fn doTheTest() !void {
225 var array_with_zero = [_:0]u8{ 'h', 'e', 'l', 'l', 'o' };
226 var zero_ptr: [*:0]const u8 = @ptrCast([*:0]const u8, &array_with_zero);
227 var no_zero_ptr: [*]const u8 = zero_ptr;
228 var zero_ptr_again = @ptrCast([*:0]const u8, no_zero_ptr);
229 try expect(std.mem.eql(u8, std.mem.spanZ(zero_ptr_again), "hello"));
230 }
231 };
232 try S.doTheTest();
233 comptime try S.doTheTest();
234}
235
236test "allow any sentinel" {
237 const S = struct {
238 fn doTheTest() !void {
239 var array = [_:std.math.minInt(i32)]i32{ 1, 2, 3, 4 };
240 var ptr: [*:std.math.minInt(i32)]i32 = &array;
241 try expect(ptr[4] == std.math.minInt(i32));
242 }
243 };
244 try S.doTheTest();
245 comptime try S.doTheTest();
246}
247
248test "pointer sentinel with enums" {
249 const S = struct {
250 const Number = enum {
251 one,
252 two,
253 sentinel,
254 };
255
256 fn doTheTest() !void {
257 var ptr: [*:.sentinel]const Number = &[_:.sentinel]Number{ .one, .two, .two, .one };
258 try expect(ptr[4] == .sentinel); // TODO this should be comptime try expect, see #3731
259 }
260 };
261 try S.doTheTest();
262 comptime try S.doTheTest();
263}
264
265test "pointer sentinel with optional element" {
266 const S = struct {
267 fn doTheTest() !void {
268 var ptr: [*:null]const ?i32 = &[_:null]?i32{ 1, 2, 3, 4 };
269 try expect(ptr[4] == null); // TODO this should be comptime try expect, see #3731
270 }
271 };
272 try S.doTheTest();
273 comptime try S.doTheTest();
274}
275
276test "pointer sentinel with +inf" {
277 const S = struct {
278 fn doTheTest() !void {
279 const inf = std.math.inf_f32;
280 var ptr: [*:inf]const f32 = &[_:inf]f32{ 1.1, 2.2, 3.3, 4.4 };
281 try expect(ptr[4] == inf); // TODO this should be comptime try expect, see #3731
282 }
283 };
284 try S.doTheTest();
285 comptime try S.doTheTest();
286}
287
288test "pointer to array at fixed address" {
289 const array = @intToPtr(*volatile [1]u32, 0x10);
290 // Silly check just to reference `array`
291 try expect(@ptrToInt(&array[0]) == 0x10);
292}
293
294test "pointer arithmetic affects the alignment" {
295 {
296 var ptr: [*]align(8) u32 = undefined;
297 var x: usize = 1;
298
299 try expect(@typeInfo(@TypeOf(ptr)).Pointer.alignment == 8);
300 const ptr1 = ptr + 1; // 1 * 4 = 4 -> lcd(4,8) = 4
301 try expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 4);
302 const ptr2 = ptr + 4; // 4 * 4 = 16 -> lcd(16,8) = 8
303 try expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 8);
304 const ptr3 = ptr + 0; // no-op
305 try expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
306 const ptr4 = ptr + x; // runtime-known addend
307 try expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
308 }
309 {
310 var ptr: [*]align(8) [3]u8 = undefined;
311 var x: usize = 1;
312
313 const ptr1 = ptr + 17; // 3 * 17 = 51
314 try expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 1);
315 const ptr2 = ptr + x; // runtime-known addend
316 try expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 1);
317 const ptr3 = ptr + 8; // 3 * 8 = 24 -> lcd(8,24) = 8
318 try expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
319 const ptr4 = ptr + 4; // 3 * 4 = 12 -> lcd(8,12) = 4
320 try expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
321 }
322}
323
324test "@ptrToInt on null optional at comptime" {
325 {
326 const pointer = @intToPtr(?*u8, 0x000);
327 const x = @ptrToInt(pointer);
328 comptime try expect(0 == @ptrToInt(pointer));
329 }
330 {
331 const pointer = @intToPtr(?*u8, 0xf00);
332 comptime try expect(0xf00 == @ptrToInt(pointer));
333 }
334}
335
336test "indexing array with sentinel returns correct type" {
337 var s: [:0]const u8 = "abc";
338 try testing.expectEqualSlices(u8, "*const u8", @typeName(@TypeOf(&s[0])));
339}
test/stage1/behavior/popcount.zig deleted-43
...@@ -1,43 +0,0 @@
1const expect = @import("std").testing.expect;
2
3test "@popCount" {
4 comptime try testPopCount();
5 try testPopCount();
6}
7
8fn testPopCount() !void {
9 {
10 var x: u32 = 0xffffffff;
11 try expect(@popCount(u32, x) == 32);
12 }
13 {
14 var x: u5 = 0x1f;
15 try expect(@popCount(u5, x) == 5);
16 }
17 {
18 var x: u32 = 0xaa;
19 try expect(@popCount(u32, x) == 4);
20 }
21 {
22 var x: u32 = 0xaaaaaaaa;
23 try expect(@popCount(u32, x) == 16);
24 }
25 {
26 var x: u32 = 0xaaaaaaaa;
27 try expect(@popCount(u32, x) == 16);
28 }
29 {
30 var x: i16 = -1;
31 try expect(@popCount(i16, x) == 16);
32 }
33 {
34 var x: i8 = -120;
35 try expect(@popCount(i8, x) == 2);
36 }
37 comptime {
38 try expect(@popCount(u8, @bitCast(u8, @as(i8, -120))) == 2);
39 }
40 comptime {
41 try expect(@popCount(i128, 0b11111111000110001100010000100001000011000011100101010001) == 24);
42 }
43}
test/stage1/behavior/ptrcast.zig deleted-72
...@@ -1,72 +0,0 @@
1const std = @import("std");
2const builtin = std.builtin;
3const expect = std.testing.expect;
4
5test "reinterpret bytes as integer with nonzero offset" {
6 try testReinterpretBytesAsInteger();
7 comptime try 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 try expect(@ptrCast(*align(1) const u32, bytes[1..5]).* == expected);
17}
18
19test "reinterpret bytes of an array into an extern struct" {
20 try testReinterpretBytesAsExternStruct();
21 comptime try 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 try expect(val == 5);
36}
37
38test "reinterpret struct field at comptime" {
39 const numNative = comptime Bytes.init(0x12345678);
40 if (builtin.endian != .Little) {
41 try expect(std.mem.eql(u8, &[_]u8{ 0x12, 0x34, 0x56, 0x78 }, &numNative.bytes));
42 } else {
43 try expect(std.mem.eql(u8, &[_]u8{ 0x78, 0x56, 0x34, 0x12 }, &numNative.bytes));
44 }
45}
46
47const Bytes = struct {
48 bytes: [4]u8,
49
50 pub fn init(v: u32) Bytes {
51 var res: Bytes = undefined;
52 @ptrCast(*align(1) u32, &res.bytes).* = v;
53
54 return res;
55 }
56};
57
58test "comptime ptrcast keeps larger alignment" {
59 comptime {
60 const a: u32 = 1234;
61 const p = @ptrCast([*]const u8, &a);
62 try expect(@TypeOf(p) == [*]align(@alignOf(u32)) const u8);
63 }
64}
65
66test "implicit optional pointer to optional c_void pointer" {
67 var buf: [4]u8 = "aoeu".*;
68 var x: ?[*]u8 = &buf;
69 var y: ?*c_void = x;
70 var z = @ptrCast(*[4]u8, y);
71 try expect(std.mem.eql(u8, z, "aoeu"));
72}
test/stage1/behavior/pub_enum.zig deleted-13
...@@ -1,13 +0,0 @@
1const other = @import("pub_enum/other.zig");
2const expect = @import("std").testing.expect;
3
4test "pub enum" {
5 try pubEnumTest(other.APubEnum.Two);
6}
7fn pubEnumTest(foo: other.APubEnum) !void {
8 try expect(foo == other.APubEnum.Two);
9}
10
11test "cast with imported symbol" {
12 try expect(@as(other.size_t, 42) == 42);
13}
test/stage1/behavior/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/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig deleted-37
...@@ -1,37 +0,0 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3
4var ok: bool = false;
5test "reference a variable in an if after an if in the 2nd switch prong" {
6 try foo(true, Num.Two, false, "aoeu");
7 try expect(!ok);
8 try foo(false, Num.One, false, "aoeu");
9 try expect(!ok);
10 try foo(true, Num.One, false, "aoeu");
11 try expect(ok);
12}
13
14const Num = enum {
15 One,
16 Two,
17};
18
19fn foo(c: bool, k: Num, c2: bool, b: []const u8) !void {
20 switch (k) {
21 Num.Two => {},
22 Num.One => {
23 if (c) {
24 const output_path = b;
25
26 if (c2) {}
27
28 try a(output_path);
29 }
30 },
31 }
32}
33
34fn a(x: []const u8) !void {
35 try expect(mem.eql(u8, x, "aoeu"));
36 ok = true;
37}
test/stage1/behavior/reflection.zig deleted-55
...@@ -1,55 +0,0 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3const reflection = @This();
4
5test "reflection: function return type, var args, and param types" {
6 comptime {
7 const info = @typeInfo(@TypeOf(dummy)).Fn;
8 try expect(info.return_type.? == i32);
9 try expect(!info.is_var_args);
10 try expect(info.args.len == 3);
11 try expect(info.args[0].arg_type.? == bool);
12 try expect(info.args[1].arg_type.? == i32);
13 try expect(info.args[2].arg_type.? == f32);
14 }
15}
16
17fn dummy(a: bool, b: i32, c: f32) i32 {
18 return 1234;
19}
20
21test "reflection: @field" {
22 var f = Foo{
23 .one = 42,
24 .two = true,
25 .three = void{},
26 };
27
28 try expect(f.one == f.one);
29 try expect(@field(f, "o" ++ "ne") == f.one);
30 try expect(@field(f, "t" ++ "wo") == f.two);
31 try expect(@field(f, "th" ++ "ree") == f.three);
32 try expect(@field(Foo, "const" ++ "ant") == Foo.constant);
33 try expect(@field(Bar, "O" ++ "ne") == Bar.One);
34 try expect(@field(Bar, "T" ++ "wo") == Bar.Two);
35 try expect(@field(Bar, "Th" ++ "ree") == Bar.Three);
36 try expect(@field(Bar, "F" ++ "our") == Bar.Four);
37 try expect(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
38 @field(f, "o" ++ "ne") = 4;
39 try expect(f.one == 4);
40}
41
42const Foo = struct {
43 const constant = 52;
44
45 one: i32,
46 two: bool,
47 three: void,
48};
49
50const Bar = union(enum) {
51 One: void,
52 Two: i32,
53 Three: bool,
54 Four: f64,
55};
test/stage1/behavior/shuffle.zig deleted-63
...@@ -1,63 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const mem = std.mem;
4const expect = std.testing.expect;
5const Vector = std.meta.Vector;
6
7test "@shuffle" {
8 // TODO investigate why this fails when cross-compiling to wasm.
9 if (builtin.os.tag == .wasi) return error.SkipZigTest;
10
11 const S = struct {
12 fn doTheTest() !void {
13 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
14 var x: Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
15 const mask: Vector(4, i32) = [4]i32{ 0, ~@as(i32, 2), 3, ~@as(i32, 3) };
16 var res = @shuffle(i32, v, x, mask);
17 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, 40, 4 }));
18
19 // Implicit cast from array (of mask)
20 res = @shuffle(i32, v, x, [4]i32{ 0, ~@as(i32, 2), 3, ~@as(i32, 3) });
21 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, 40, 4 }));
22
23 // Undefined
24 const mask2: Vector(4, i32) = [4]i32{ 3, 1, 2, 0 };
25 res = @shuffle(i32, v, undefined, mask2);
26 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 40, -2, 30, 2147483647 }));
27
28 // Upcasting of b
29 var v2: Vector(2, i32) = [2]i32{ 2147483647, undefined };
30 const mask3: Vector(4, i32) = [4]i32{ ~@as(i32, 0), 2, ~@as(i32, 0), 3 };
31 res = @shuffle(i32, x, v2, mask3);
32 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, 2147483647, 4 }));
33
34 // Upcasting of a
35 var v3: Vector(2, i32) = [2]i32{ 2147483647, -2 };
36 const mask4: Vector(4, i32) = [4]i32{ 0, ~@as(i32, 2), 1, ~@as(i32, 3) };
37 res = @shuffle(i32, v3, x, mask4);
38 try expect(mem.eql(i32, &@as([4]i32, res), &[4]i32{ 2147483647, 3, -2, 4 }));
39
40 // bool
41 // Disabled because of #3317
42 if (@import("builtin").arch != .mipsel and std.Target.current.cpu.arch != .mips) {
43 var x2: Vector(4, bool) = [4]bool{ false, true, false, true };
44 var v4: Vector(2, bool) = [2]bool{ true, false };
45 const mask5: Vector(4, i32) = [4]i32{ 0, ~@as(i32, 1), 1, 2 };
46 var res2 = @shuffle(bool, x2, v4, mask5);
47 try expect(mem.eql(bool, &@as([4]bool, res2), &[4]bool{ false, false, true, false }));
48 }
49
50 // TODO re-enable when LLVM codegen is fixed
51 // https://github.com/ziglang/zig/issues/3246
52 if (false) {
53 var x2: Vector(3, bool) = [3]bool{ false, true, false };
54 var v4: Vector(2, bool) = [2]bool{ true, false };
55 const mask5: Vector(4, i32) = [4]i32{ 0, ~@as(i32, 1), 1, 2 };
56 var res2 = @shuffle(bool, x2, v4, mask5);
57 try expect(mem.eql(bool, &@as([4]bool, res2), &[4]bool{ false, false, true, false }));
58 }
59 }
60 };
61 try S.doTheTest();
62 comptime try S.doTheTest();
63}
test/stage1/behavior/sizeof_and_typeof.zig deleted-264
...@@ -1,264 +0,0 @@
1const std = @import("std");
2const builtin = std.builtin;
3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;
5
6test "@sizeOf and @TypeOf" {
7 const y: @TypeOf(x) = 120;
8 try expect(@sizeOf(@TypeOf(y)) == 2);
9}
10const x: u16 = 13;
11const z: @TypeOf(x) = 19;
12
13const A = struct {
14 a: u8,
15 b: u32,
16 c: u8,
17 d: u3,
18 e: u5,
19 f: u16,
20 g: u16,
21 h: u9,
22 i: u7,
23};
24
25const P = packed struct {
26 a: u8,
27 b: u32,
28 c: u8,
29 d: u3,
30 e: u5,
31 f: u16,
32 g: u16,
33 h: u9,
34 i: u7,
35};
36
37test "@byteOffsetOf" {
38 // Packed structs have fixed memory layout
39 try expect(@byteOffsetOf(P, "a") == 0);
40 try expect(@byteOffsetOf(P, "b") == 1);
41 try expect(@byteOffsetOf(P, "c") == 5);
42 try expect(@byteOffsetOf(P, "d") == 6);
43 try expect(@byteOffsetOf(P, "e") == 6);
44 try expect(@byteOffsetOf(P, "f") == 7);
45 try expect(@byteOffsetOf(P, "g") == 9);
46 try expect(@byteOffsetOf(P, "h") == 11);
47 try expect(@byteOffsetOf(P, "i") == 12);
48
49 // Normal struct fields can be moved/padded
50 var a: A = undefined;
51 try expect(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
52 try expect(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
53 try expect(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
54 try expect(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
55 try expect(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
56 try expect(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
57 try expect(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
58 try expect(@ptrToInt(&a.h) - @ptrToInt(&a) == @byteOffsetOf(A, "h"));
59 try expect(@ptrToInt(&a.i) - @ptrToInt(&a) == @byteOffsetOf(A, "i"));
60}
61
62test "@byteOffsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" {
63 const p3a_len = 3;
64 const P3 = packed struct {
65 a: [p3a_len]u8,
66 b: usize,
67 };
68 try std.testing.expectEqual(0, @byteOffsetOf(P3, "a"));
69 try std.testing.expectEqual(p3a_len, @byteOffsetOf(P3, "b"));
70
71 const p5a_len = 5;
72 const P5 = packed struct {
73 a: [p5a_len]u8,
74 b: usize,
75 };
76 try std.testing.expectEqual(0, @byteOffsetOf(P5, "a"));
77 try std.testing.expectEqual(p5a_len, @byteOffsetOf(P5, "b"));
78
79 const p6a_len = 6;
80 const P6 = packed struct {
81 a: [p6a_len]u8,
82 b: usize,
83 };
84 try std.testing.expectEqual(0, @byteOffsetOf(P6, "a"));
85 try std.testing.expectEqual(p6a_len, @byteOffsetOf(P6, "b"));
86
87 const p7a_len = 7;
88 const P7 = packed struct {
89 a: [p7a_len]u8,
90 b: usize,
91 };
92 try std.testing.expectEqual(0, @byteOffsetOf(P7, "a"));
93 try std.testing.expectEqual(p7a_len, @byteOffsetOf(P7, "b"));
94
95 const p9a_len = 9;
96 const P9 = packed struct {
97 a: [p9a_len]u8,
98 b: usize,
99 };
100 try std.testing.expectEqual(0, @byteOffsetOf(P9, "a"));
101 try std.testing.expectEqual(p9a_len, @byteOffsetOf(P9, "b"));
102
103 // 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 25 etc. are further cases
104}
105
106test "@bitOffsetOf" {
107 // Packed structs have fixed memory layout
108 try expect(@bitOffsetOf(P, "a") == 0);
109 try expect(@bitOffsetOf(P, "b") == 8);
110 try expect(@bitOffsetOf(P, "c") == 40);
111 try expect(@bitOffsetOf(P, "d") == 48);
112 try expect(@bitOffsetOf(P, "e") == 51);
113 try expect(@bitOffsetOf(P, "f") == 56);
114 try expect(@bitOffsetOf(P, "g") == 72);
115
116 try expect(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
117 try expect(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
118 try expect(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
119 try expect(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
120 try expect(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
121 try expect(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
122 try expect(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
123}
124
125test "@sizeOf on compile-time types" {
126 try expect(@sizeOf(comptime_int) == 0);
127 try expect(@sizeOf(comptime_float) == 0);
128 try expect(@sizeOf(@TypeOf(.hi)) == 0);
129 try expect(@sizeOf(@TypeOf(type)) == 0);
130}
131
132test "@sizeOf(T) == 0 doesn't force resolving struct size" {
133 const S = struct {
134 const Foo = struct {
135 y: if (@sizeOf(Foo) == 0) u64 else u32,
136 };
137 const Bar = struct {
138 x: i32,
139 y: if (0 == @sizeOf(Bar)) u64 else u32,
140 };
141 };
142
143 try expect(@sizeOf(S.Foo) == 4);
144 try expect(@sizeOf(S.Bar) == 8);
145}
146
147test "@TypeOf() has no runtime side effects" {
148 const S = struct {
149 fn foo(comptime T: type, ptr: *T) T {
150 ptr.* += 1;
151 return ptr.*;
152 }
153 };
154 var data: i32 = 0;
155 const T = @TypeOf(S.foo(i32, &data));
156 comptime try expect(T == i32);
157 try expect(data == 0);
158}
159
160test "@TypeOf() with multiple arguments" {
161 {
162 var var_1: u32 = undefined;
163 var var_2: u8 = undefined;
164 var var_3: u64 = undefined;
165 comptime try expect(@TypeOf(var_1, var_2, var_3) == u64);
166 }
167 {
168 var var_1: f16 = undefined;
169 var var_2: f32 = undefined;
170 var var_3: f64 = undefined;
171 comptime try expect(@TypeOf(var_1, var_2, var_3) == f64);
172 }
173 {
174 var var_1: u16 = undefined;
175 comptime try expect(@TypeOf(var_1, 0xffff) == u16);
176 }
177 {
178 var var_1: f32 = undefined;
179 comptime try expect(@TypeOf(var_1, 3.1415) == f32);
180 }
181}
182
183test "branching logic inside @TypeOf" {
184 const S = struct {
185 var data: i32 = 0;
186 fn foo() anyerror!i32 {
187 data += 1;
188 return undefined;
189 }
190 };
191 const T = @TypeOf(S.foo() catch undefined);
192 comptime try expect(T == i32);
193 try expect(S.data == 0);
194}
195
196fn fn1(alpha: bool) void {
197 const n: usize = 7;
198 const v = if (alpha) n else @sizeOf(usize);
199}
200
201test "lazy @sizeOf result is checked for definedness" {
202 const f = fn1;
203}
204
205test "@bitSizeOf" {
206 try expect(@bitSizeOf(u2) == 2);
207 try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);
208 try expect(@bitSizeOf(struct {
209 a: u2,
210 }) == 8);
211 try expect(@bitSizeOf(packed struct {
212 a: u2,
213 }) == 2);
214}
215
216test "@sizeOf comparison against zero" {
217 const S0 = struct {
218 f: *@This(),
219 };
220 const U0 = union {
221 f: *@This(),
222 };
223 const S1 = struct {
224 fn H(comptime T: type) type {
225 return struct {
226 x: T,
227 };
228 }
229 f0: H(*@This()),
230 f1: H(**@This()),
231 f2: H(***@This()),
232 };
233 const U1 = union {
234 fn H(comptime T: type) type {
235 return struct {
236 x: T,
237 };
238 }
239 f0: H(*@This()),
240 f1: H(**@This()),
241 f2: H(***@This()),
242 };
243 const S = struct {
244 fn doTheTest(comptime T: type, comptime result: bool) !void {
245 try expectEqual(result, @sizeOf(T) > 0);
246 }
247 };
248 // Zero-sized type
249 try S.doTheTest(u0, false);
250 try S.doTheTest(*u0, false);
251 // Non byte-sized type
252 try S.doTheTest(u1, true);
253 try S.doTheTest(*u1, true);
254 // Regular type
255 try S.doTheTest(u8, true);
256 try S.doTheTest(*u8, true);
257 try S.doTheTest(f32, true);
258 try S.doTheTest(*f32, true);
259 // Container with ptr pointing to themselves
260 try S.doTheTest(S0, true);
261 try S.doTheTest(U0, true);
262 try S.doTheTest(S1, true);
263 try S.doTheTest(U1, true);
264}
test/stage1/behavior/slice.zig deleted-337
...@@ -1,337 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
4const expectEqual = std.testing.expectEqual;
5const mem = std.mem;
6
7const x = @intToPtr([*]i32, 0x1000)[0..0x500];
8const y = x[0x100..];
9test "compile time slice of pointer to hard coded address" {
10 try expect(@ptrToInt(x) == 0x1000);
11 try expect(x.len == 0x500);
12
13 try expect(@ptrToInt(y) == 0x1100);
14 try expect(y.len == 0x400);
15}
16
17test "runtime safety lets us slice from len..len" {
18 var an_array = [_]u8{
19 1,
20 2,
21 3,
22 };
23 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
24}
25
26fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
27 return a_slice[start..end];
28}
29
30test "implicitly cast array of size 0 to slice" {
31 var msg = [_]u8{};
32 try assertLenIsZero(&msg);
33}
34
35fn assertLenIsZero(msg: []const u8) !void {
36 try expect(msg.len == 0);
37}
38
39test "C pointer" {
40 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
41 var len: u32 = 10;
42 var slice = buf[0..len];
43 try expectEqualSlices(u8, "kjdhfkjdhf", slice);
44}
45
46test "C pointer slice access" {
47 var buf: [10]u32 = [1]u32{42} ** 10;
48 const c_ptr = @ptrCast([*c]const u32, &buf);
49
50 var runtime_zero: usize = 0;
51 comptime try expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
52 comptime try expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
53
54 for (c_ptr[0..5]) |*cl| {
55 try expectEqual(@as(u32, 42), cl.*);
56 }
57}
58
59fn sliceSum(comptime q: []const u8) i32 {
60 comptime var result = 0;
61 inline for (q) |item| {
62 result += item;
63 }
64 return result;
65}
66
67test "comptime slices are disambiguated" {
68 try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
69 try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
70}
71
72test "slice type with custom alignment" {
73 const LazilyResolvedType = struct {
74 anything: i32,
75 };
76 var slice: []align(32) LazilyResolvedType = undefined;
77 var array: [10]LazilyResolvedType align(32) = undefined;
78 slice = &array;
79 slice[1].anything = 42;
80 try expect(array[1].anything == 42);
81}
82
83test "access len index of sentinel-terminated slice" {
84 const S = struct {
85 fn doTheTest() !void {
86 var slice: [:0]const u8 = "hello";
87
88 try expect(slice.len == 5);
89 try expect(slice[5] == 0);
90 }
91 };
92 try S.doTheTest();
93 comptime try S.doTheTest();
94}
95
96test "obtaining a null terminated slice" {
97 // here we have a normal array
98 var buf: [50]u8 = undefined;
99
100 buf[0] = 'a';
101 buf[1] = 'b';
102 buf[2] = 'c';
103 buf[3] = 0;
104
105 // now we obtain a null terminated slice:
106 const ptr = buf[0..3 :0];
107
108 var runtime_len: usize = 3;
109 const ptr2 = buf[0..runtime_len :0];
110 // ptr2 is a null-terminated slice
111 comptime try expect(@TypeOf(ptr2) == [:0]u8);
112 comptime try expect(@TypeOf(ptr2[0..2]) == *[2]u8);
113 var runtime_zero: usize = 0;
114 comptime try expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
115}
116
117test "empty array to slice" {
118 const S = struct {
119 fn doTheTest() !void {
120 const empty: []align(16) u8 = &[_]u8{};
121 const align_1: []align(1) u8 = empty;
122 const align_4: []align(4) u8 = empty;
123 const align_16: []align(16) u8 = empty;
124 try expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment);
125 try expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment);
126 try expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment);
127 }
128 };
129
130 try S.doTheTest();
131 comptime try S.doTheTest();
132}
133
134test "@ptrCast slice to pointer" {
135 const S = struct {
136 fn doTheTest() !void {
137 var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
138 var slice: []u8 = &array;
139 var ptr = @ptrCast(*u16, slice);
140 try expect(ptr.* == 65535);
141 }
142 };
143
144 try S.doTheTest();
145 comptime try S.doTheTest();
146}
147
148test "slice syntax resulting in pointer-to-array" {
149 const S = struct {
150 fn doTheTest() !void {
151 try testArray();
152 try testArrayZ();
153 try testArray0();
154 try testArrayAlign();
155 try testPointer();
156 try testPointerZ();
157 try testPointer0();
158 try testPointerAlign();
159 try testSlice();
160 try testSliceZ();
161 try testSlice0();
162 try testSliceOpt();
163 try testSliceAlign();
164 }
165
166 fn testArray() !void {
167 var array = [5]u8{ 1, 2, 3, 4, 5 };
168 var slice = array[1..3];
169 comptime try expect(@TypeOf(slice) == *[2]u8);
170 try expect(slice[0] == 2);
171 try expect(slice[1] == 3);
172 }
173
174 fn testArrayZ() !void {
175 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
176 comptime try expect(@TypeOf(array[1..3]) == *[2]u8);
177 comptime try expect(@TypeOf(array[1..5]) == *[4:0]u8);
178 comptime try expect(@TypeOf(array[1..]) == *[4:0]u8);
179 comptime try expect(@TypeOf(array[1..3 :4]) == *[2:4]u8);
180 }
181
182 fn testArray0() !void {
183 {
184 var array = [0]u8{};
185 var slice = array[0..0];
186 comptime try expect(@TypeOf(slice) == *[0]u8);
187 }
188 {
189 var array = [0:0]u8{};
190 var slice = array[0..0];
191 comptime try expect(@TypeOf(slice) == *[0:0]u8);
192 try expect(slice[0] == 0);
193 }
194 }
195
196 fn testArrayAlign() !void {
197 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
198 var slice = array[4..5];
199 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
200 try expect(slice[0] == 5);
201 comptime try expect(@TypeOf(array[0..2]) == *align(4) [2]u8);
202 }
203
204 fn testPointer() !void {
205 var array = [5]u8{ 1, 2, 3, 4, 5 };
206 var pointer: [*]u8 = &array;
207 var slice = pointer[1..3];
208 comptime try expect(@TypeOf(slice) == *[2]u8);
209 try expect(slice[0] == 2);
210 try expect(slice[1] == 3);
211 }
212
213 fn testPointerZ() !void {
214 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
215 var pointer: [*:0]u8 = &array;
216 comptime try expect(@TypeOf(pointer[1..3]) == *[2]u8);
217 comptime try expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
218 }
219
220 fn testPointer0() !void {
221 var pointer: [*]const u0 = &[1]u0{0};
222 var slice = pointer[0..1];
223 comptime try expect(@TypeOf(slice) == *const [1]u0);
224 try expect(slice[0] == 0);
225 }
226
227 fn testPointerAlign() !void {
228 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
229 var pointer: [*]align(4) u8 = &array;
230 var slice = pointer[4..5];
231 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
232 try expect(slice[0] == 5);
233 comptime try expect(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
234 }
235
236 fn testSlice() !void {
237 var array = [5]u8{ 1, 2, 3, 4, 5 };
238 var src_slice: []u8 = &array;
239 var slice = src_slice[1..3];
240 comptime try expect(@TypeOf(slice) == *[2]u8);
241 try expect(slice[0] == 2);
242 try expect(slice[1] == 3);
243 }
244
245 fn testSliceZ() !void {
246 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
247 var slice: [:0]u8 = &array;
248 comptime try expect(@TypeOf(slice[1..3]) == *[2]u8);
249 comptime try expect(@TypeOf(slice[1..]) == [:0]u8);
250 comptime try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
251 }
252
253 fn testSliceOpt() !void {
254 var array: [2]u8 = [2]u8{ 1, 2 };
255 var slice: ?[]u8 = &array;
256 comptime try expect(@TypeOf(&array, slice) == ?[]u8);
257 comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8);
258 }
259
260 fn testSlice0() !void {
261 {
262 var array = [0]u8{};
263 var src_slice: []u8 = &array;
264 var slice = src_slice[0..0];
265 comptime try expect(@TypeOf(slice) == *[0]u8);
266 }
267 {
268 var array = [0:0]u8{};
269 var src_slice: [:0]u8 = &array;
270 var slice = src_slice[0..0];
271 comptime try expect(@TypeOf(slice) == *[0]u8);
272 }
273 }
274
275 fn testSliceAlign() !void {
276 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
277 var src_slice: []align(4) u8 = &array;
278 var slice = src_slice[4..5];
279 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
280 try expect(slice[0] == 5);
281 comptime try expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
282 }
283
284 fn testConcatStrLiterals() !void {
285 try expectEqualSlices("a"[0..] ++ "b"[0..], "ab");
286 try expectEqualSlices("a"[0.. :0] ++ "b"[0.. :0], "ab");
287 }
288 };
289
290 try S.doTheTest();
291 comptime try S.doTheTest();
292}
293
294test "slice of hardcoded address to pointer" {
295 const S = struct {
296 fn doTheTest() !void {
297 const pointer = @intToPtr([*]u8, 0x04)[0..2];
298 comptime try expect(@TypeOf(pointer) == *[2]u8);
299 const slice: []const u8 = pointer;
300 try expect(@ptrToInt(slice.ptr) == 4);
301 try expect(slice.len == 2);
302 }
303 };
304
305 try S.doTheTest();
306}
307
308test "type coercion of pointer to anon struct literal to pointer to slice" {
309 const S = struct {
310 const U = union {
311 a: u32,
312 b: bool,
313 c: []const u8,
314 };
315
316 fn doTheTest() !void {
317 var x1: u8 = 42;
318 const t1 = &.{ x1, 56, 54 };
319 var slice1: []const u8 = t1;
320 try expect(slice1.len == 3);
321 try expect(slice1[0] == 42);
322 try expect(slice1[1] == 56);
323 try expect(slice1[2] == 54);
324
325 var x2: []const u8 = "hello";
326 const t2 = &.{ x2, ", ", "world!" };
327 // @compileLog(@TypeOf(t2));
328 var slice2: []const []const u8 = t2;
329 try expect(slice2.len == 3);
330 try expect(mem.eql(u8, slice2[0], "hello"));
331 try expect(mem.eql(u8, slice2[1], ", "));
332 try expect(mem.eql(u8, slice2[2], "world!"));
333 }
334 };
335 // try S.doTheTest();
336 comptime try S.doTheTest();
337}
test/stage1/behavior/slice_sentinel_comptime.zig deleted-199
...@@ -1,199 +0,0 @@
1test "comptime slice-sentinel in bounds (unterminated)" {
2 // array
3 comptime {
4 var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
5 const slice = target[0..3 :'d'];
6 }
7
8 // ptr_array
9 comptime {
10 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..3 :'d'];
13 }
14
15 // vector_ConstPtrSpecialBaseArray
16 comptime {
17 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
18 var target: [*]u8 = &buf;
19 const slice = target[0..3 :'d'];
20 }
21
22 // vector_ConstPtrSpecialRef
23 comptime {
24 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
25 var target: [*]u8 = @ptrCast([*]u8, &buf);
26 const slice = target[0..3 :'d'];
27 }
28
29 // cvector_ConstPtrSpecialBaseArray
30 comptime {
31 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
32 var target: [*c]u8 = &buf;
33 const slice = target[0..3 :'d'];
34 }
35
36 // cvector_ConstPtrSpecialRef
37 comptime {
38 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
39 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
40 const slice = target[0..3 :'d'];
41 }
42
43 // slice
44 comptime {
45 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
46 var target: []u8 = &buf;
47 const slice = target[0..3 :'d'];
48 }
49}
50
51test "comptime slice-sentinel in bounds (end,unterminated)" {
52 // array
53 comptime {
54 var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
55 const slice = target[0..13 :0xff];
56 }
57
58 // ptr_array
59 comptime {
60 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
61 var target = &buf;
62 const slice = target[0..13 :0xff];
63 }
64
65 // vector_ConstPtrSpecialBaseArray
66 comptime {
67 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
68 var target: [*]u8 = &buf;
69 const slice = target[0..13 :0xff];
70 }
71
72 // vector_ConstPtrSpecialRef
73 comptime {
74 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
75 var target: [*]u8 = @ptrCast([*]u8, &buf);
76 const slice = target[0..13 :0xff];
77 }
78
79 // cvector_ConstPtrSpecialBaseArray
80 comptime {
81 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
82 var target: [*c]u8 = &buf;
83 const slice = target[0..13 :0xff];
84 }
85
86 // cvector_ConstPtrSpecialRef
87 comptime {
88 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
89 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
90 const slice = target[0..13 :0xff];
91 }
92
93 // slice
94 comptime {
95 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{0xff} ** 10;
96 var target: []u8 = &buf;
97 const slice = target[0..13 :0xff];
98 }
99}
100
101test "comptime slice-sentinel in bounds (terminated)" {
102 // array
103 comptime {
104 var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
105 const slice = target[0..3 :'d'];
106 }
107
108 // ptr_array
109 comptime {
110 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
111 var target = &buf;
112 const slice = target[0..3 :'d'];
113 }
114
115 // vector_ConstPtrSpecialBaseArray
116 comptime {
117 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
118 var target: [*]u8 = &buf;
119 const slice = target[0..3 :'d'];
120 }
121
122 // vector_ConstPtrSpecialRef
123 comptime {
124 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
125 var target: [*]u8 = @ptrCast([*]u8, &buf);
126 const slice = target[0..3 :'d'];
127 }
128
129 // cvector_ConstPtrSpecialBaseArray
130 comptime {
131 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
132 var target: [*c]u8 = &buf;
133 const slice = target[0..3 :'d'];
134 }
135
136 // cvector_ConstPtrSpecialRef
137 comptime {
138 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
139 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
140 const slice = target[0..3 :'d'];
141 }
142
143 // slice
144 comptime {
145 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
146 var target: []u8 = &buf;
147 const slice = target[0..3 :'d'];
148 }
149}
150
151test "comptime slice-sentinel in bounds (on target sentinel)" {
152 // array
153 comptime {
154 var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
155 const slice = target[0..14 :0];
156 }
157
158 // ptr_array
159 comptime {
160 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
161 var target = &buf;
162 const slice = target[0..14 :0];
163 }
164
165 // vector_ConstPtrSpecialBaseArray
166 comptime {
167 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
168 var target: [*]u8 = &buf;
169 const slice = target[0..14 :0];
170 }
171
172 // vector_ConstPtrSpecialRef
173 comptime {
174 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
175 var target: [*]u8 = @ptrCast([*]u8, &buf);
176 const slice = target[0..14 :0];
177 }
178
179 // cvector_ConstPtrSpecialBaseArray
180 comptime {
181 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
182 var target: [*c]u8 = &buf;
183 const slice = target[0..14 :0];
184 }
185
186 // cvector_ConstPtrSpecialRef
187 comptime {
188 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
189 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
190 const slice = target[0..14 :0];
191 }
192
193 // slice
194 comptime {
195 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
196 var target: []u8 = &buf;
197 const slice = target[0..14 :0];
198 }
199}
test/stage1/behavior/src.zig deleted-17
...@@ -1,17 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "@src" {
5 try doTheTest();
6}
7
8fn doTheTest() !void {
9 const src = @src();
10
11 try expect(src.line == 9);
12 try expect(src.column == 17);
13 try expect(std.mem.endsWith(u8, src.fn_name, "doTheTest"));
14 try expect(std.mem.endsWith(u8, src.file, "src.zig"));
15 try expect(src.fn_name[src.fn_name.len] == 0);
16 try expect(src.file[src.file.len] == 0);
17}
test/stage1/behavior/struct.zig deleted-945
...@@ -1,945 +0,0 @@
1const std = @import("std");
2const builtin = std.builtin;
3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;
5const expectEqualSlices = std.testing.expectEqualSlices;
6const maxInt = std.math.maxInt;
7const StructWithNoFields = struct {
8 fn add(a: i32, b: i32) i32 {
9 return a + b;
10 }
11};
12const empty_global_instance = StructWithNoFields{};
13
14top_level_field: i32,
15
16test "top level fields" {
17 var instance = @This(){
18 .top_level_field = 1234,
19 };
20 instance.top_level_field += 1;
21 try expectEqual(@as(i32, 1235), instance.top_level_field);
22}
23
24test "call struct static method" {
25 const result = StructWithNoFields.add(3, 4);
26 try expect(result == 7);
27}
28
29test "return empty struct instance" {
30 _ = returnEmptyStructInstance();
31}
32fn returnEmptyStructInstance() StructWithNoFields {
33 return empty_global_instance;
34}
35
36const should_be_11 = StructWithNoFields.add(5, 6);
37
38test "invoke static method in global scope" {
39 try expect(should_be_11 == 11);
40}
41
42test "void struct fields" {
43 const foo = VoidStructFieldsFoo{
44 .a = void{},
45 .b = 1,
46 .c = void{},
47 };
48 try expect(foo.b == 1);
49 try expect(@sizeOf(VoidStructFieldsFoo) == 4);
50}
51const VoidStructFieldsFoo = struct {
52 a: void,
53 b: i32,
54 c: void,
55};
56
57test "structs" {
58 var foo: StructFoo = undefined;
59 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
60 foo.a += 1;
61 foo.b = foo.a == 1;
62 try testFoo(foo);
63 testMutation(&foo);
64 try expect(foo.c == 100);
65}
66const StructFoo = struct {
67 a: i32,
68 b: bool,
69 c: f32,
70};
71fn testFoo(foo: StructFoo) !void {
72 try expect(foo.b);
73}
74fn testMutation(foo: *StructFoo) void {
75 foo.c = 100;
76}
77
78const Node = struct {
79 val: Val,
80 next: *Node,
81};
82
83const Val = struct {
84 x: i32,
85};
86
87test "struct point to self" {
88 var root: Node = undefined;
89 root.val.x = 1;
90
91 var node: Node = undefined;
92 node.next = &root;
93 node.val.x = 2;
94
95 root.next = &node;
96
97 try expect(node.next.next.next.val.x == 1);
98}
99
100test "struct byval assign" {
101 var foo1: StructFoo = undefined;
102 var foo2: StructFoo = undefined;
103
104 foo1.a = 1234;
105 foo2.a = 0;
106 try expect(foo2.a == 0);
107 foo2 = foo1;
108 try expect(foo2.a == 1234);
109}
110
111fn structInitializer() void {
112 const val = Val{ .x = 42 };
113 try expect(val.x == 42);
114}
115
116test "fn call of struct field" {
117 const Foo = struct {
118 ptr: fn () i32,
119 };
120 const S = struct {
121 fn aFunc() i32 {
122 return 13;
123 }
124
125 fn callStructField(foo: Foo) i32 {
126 return foo.ptr();
127 }
128 };
129
130 try expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13);
131}
132
133test "store member function in variable" {
134 const instance = MemberFnTestFoo{ .x = 1234 };
135 const memberFn = MemberFnTestFoo.member;
136 const result = memberFn(instance);
137 try expect(result == 1234);
138}
139const MemberFnTestFoo = struct {
140 x: i32,
141 fn member(foo: MemberFnTestFoo) i32 {
142 return foo.x;
143 }
144};
145
146test "call member function directly" {
147 const instance = MemberFnTestFoo{ .x = 1234 };
148 const result = MemberFnTestFoo.member(instance);
149 try expect(result == 1234);
150}
151
152test "member functions" {
153 const r = MemberFnRand{ .seed = 1234 };
154 try expect(r.getSeed() == 1234);
155}
156const MemberFnRand = struct {
157 seed: u32,
158 pub fn getSeed(r: *const MemberFnRand) u32 {
159 return r.seed;
160 }
161};
162
163test "return struct byval from function" {
164 const bar = makeBar(1234, 5678);
165 try expect(bar.y == 5678);
166}
167const Bar = struct {
168 x: i32,
169 y: i32,
170};
171fn makeBar(x: i32, y: i32) Bar {
172 return Bar{
173 .x = x,
174 .y = y,
175 };
176}
177
178test "empty struct method call" {
179 const es = EmptyStruct{};
180 try expect(es.method() == 1234);
181}
182const EmptyStruct = struct {
183 fn method(es: *const EmptyStruct) i32 {
184 return 1234;
185 }
186};
187
188test "return empty struct from fn" {
189 _ = testReturnEmptyStructFromFn();
190}
191const EmptyStruct2 = struct {};
192fn testReturnEmptyStructFromFn() EmptyStruct2 {
193 return EmptyStruct2{};
194}
195
196test "pass slice of empty struct to fn" {
197 try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1);
198}
199fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
200 return slice.len;
201}
202
203const APackedStruct = packed struct {
204 x: u8,
205 y: u8,
206};
207
208test "packed struct" {
209 var foo = APackedStruct{
210 .x = 1,
211 .y = 2,
212 };
213 foo.y += 1;
214 const four = foo.x + foo.y;
215 try expect(four == 4);
216}
217
218const BitField1 = packed struct {
219 a: u3,
220 b: u3,
221 c: u2,
222};
223
224const bit_field_1 = BitField1{
225 .a = 1,
226 .b = 2,
227 .c = 3,
228};
229
230test "bit field access" {
231 var data = bit_field_1;
232 try expect(getA(&data) == 1);
233 try expect(getB(&data) == 2);
234 try expect(getC(&data) == 3);
235 comptime try expect(@sizeOf(BitField1) == 1);
236
237 data.b += 1;
238 try expect(data.b == 3);
239
240 data.a += 1;
241 try expect(data.a == 2);
242 try expect(data.b == 3);
243}
244
245fn getA(data: *const BitField1) u3 {
246 return data.a;
247}
248
249fn getB(data: *const BitField1) u3 {
250 return data.b;
251}
252
253fn getC(data: *const BitField1) u2 {
254 return data.c;
255}
256
257const Foo24Bits = packed struct {
258 field: u24,
259};
260const Foo96Bits = packed struct {
261 a: u24,
262 b: u24,
263 c: u24,
264 d: u24,
265};
266
267test "packed struct 24bits" {
268 comptime {
269 try expect(@sizeOf(Foo24Bits) == 4);
270 if (@sizeOf(usize) == 4) {
271 try expect(@sizeOf(Foo96Bits) == 12);
272 } else {
273 try expect(@sizeOf(Foo96Bits) == 16);
274 }
275 }
276
277 var value = Foo96Bits{
278 .a = 0,
279 .b = 0,
280 .c = 0,
281 .d = 0,
282 };
283 value.a += 1;
284 try expect(value.a == 1);
285 try expect(value.b == 0);
286 try expect(value.c == 0);
287 try expect(value.d == 0);
288
289 value.b += 1;
290 try expect(value.a == 1);
291 try expect(value.b == 1);
292 try expect(value.c == 0);
293 try expect(value.d == 0);
294
295 value.c += 1;
296 try expect(value.a == 1);
297 try expect(value.b == 1);
298 try expect(value.c == 1);
299 try expect(value.d == 0);
300
301 value.d += 1;
302 try expect(value.a == 1);
303 try expect(value.b == 1);
304 try expect(value.c == 1);
305 try expect(value.d == 1);
306}
307
308const Foo32Bits = packed struct {
309 field: u24,
310 pad: u8,
311};
312
313const FooArray24Bits = packed struct {
314 a: u16,
315 b: [2]Foo32Bits,
316 c: u16,
317};
318
319// TODO revisit this test when doing https://github.com/ziglang/zig/issues/1512
320test "packed array 24bits" {
321 comptime {
322 try expect(@sizeOf([9]Foo32Bits) == 9 * 4);
323 try expect(@sizeOf(FooArray24Bits) == 2 + 2 * 4 + 2);
324 }
325
326 var bytes = [_]u8{0} ** (@sizeOf(FooArray24Bits) + 1);
327 bytes[bytes.len - 1] = 0xaa;
328 const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
329 try expect(ptr.a == 0);
330 try expect(ptr.b[0].field == 0);
331 try expect(ptr.b[1].field == 0);
332 try expect(ptr.c == 0);
333
334 ptr.a = maxInt(u16);
335 try expect(ptr.a == maxInt(u16));
336 try expect(ptr.b[0].field == 0);
337 try expect(ptr.b[1].field == 0);
338 try expect(ptr.c == 0);
339
340 ptr.b[0].field = maxInt(u24);
341 try expect(ptr.a == maxInt(u16));
342 try expect(ptr.b[0].field == maxInt(u24));
343 try expect(ptr.b[1].field == 0);
344 try expect(ptr.c == 0);
345
346 ptr.b[1].field = maxInt(u24);
347 try expect(ptr.a == maxInt(u16));
348 try expect(ptr.b[0].field == maxInt(u24));
349 try expect(ptr.b[1].field == maxInt(u24));
350 try expect(ptr.c == 0);
351
352 ptr.c = maxInt(u16);
353 try expect(ptr.a == maxInt(u16));
354 try expect(ptr.b[0].field == maxInt(u24));
355 try expect(ptr.b[1].field == maxInt(u24));
356 try expect(ptr.c == maxInt(u16));
357
358 try expect(bytes[bytes.len - 1] == 0xaa);
359}
360
361const FooStructAligned = packed struct {
362 a: u8,
363 b: u8,
364};
365
366const FooArrayOfAligned = packed struct {
367 a: [2]FooStructAligned,
368};
369
370test "aligned array of packed struct" {
371 comptime {
372 try expect(@sizeOf(FooStructAligned) == 2);
373 try expect(@sizeOf(FooArrayOfAligned) == 2 * 2);
374 }
375
376 var bytes = [_]u8{0xbb} ** @sizeOf(FooArrayOfAligned);
377 const ptr = &std.mem.bytesAsSlice(FooArrayOfAligned, bytes[0..])[0];
378
379 try expect(ptr.a[0].a == 0xbb);
380 try expect(ptr.a[0].b == 0xbb);
381 try expect(ptr.a[1].a == 0xbb);
382 try expect(ptr.a[1].b == 0xbb);
383}
384
385test "runtime struct initialization of bitfield" {
386 const s1 = Nibbles{
387 .x = x1,
388 .y = x1,
389 };
390 const s2 = Nibbles{
391 .x = @intCast(u4, x2),
392 .y = @intCast(u4, x2),
393 };
394
395 try expect(s1.x == x1);
396 try expect(s1.y == x1);
397 try expect(s2.x == @intCast(u4, x2));
398 try expect(s2.y == @intCast(u4, x2));
399}
400
401var x1 = @as(u4, 1);
402var x2 = @as(u8, 2);
403
404const Nibbles = packed struct {
405 x: u4,
406 y: u4,
407};
408
409const Bitfields = packed struct {
410 f1: u16,
411 f2: u16,
412 f3: u8,
413 f4: u8,
414 f5: u4,
415 f6: u4,
416 f7: u8,
417};
418
419test "native bit field understands endianness" {
420 var all: u64 = if (builtin.endian != .Little)
421 0x1111222233445677
422 else
423 0x7765443322221111;
424 var bytes: [8]u8 = undefined;
425 @memcpy(&bytes, @ptrCast([*]u8, &all), 8);
426 var bitfields = @ptrCast(*Bitfields, &bytes).*;
427
428 try expect(bitfields.f1 == 0x1111);
429 try expect(bitfields.f2 == 0x2222);
430 try expect(bitfields.f3 == 0x33);
431 try expect(bitfields.f4 == 0x44);
432 try expect(bitfields.f5 == 0x5);
433 try expect(bitfields.f6 == 0x6);
434 try expect(bitfields.f7 == 0x77);
435}
436
437test "align 1 field before self referential align 8 field as slice return type" {
438 const result = alloc(Expr);
439 try expect(result.len == 0);
440}
441
442const Expr = union(enum) {
443 Literal: u8,
444 Question: *Expr,
445};
446
447fn alloc(comptime T: type) []T {
448 return &[_]T{};
449}
450
451test "call method with mutable reference to struct with no fields" {
452 const S = struct {
453 fn doC(s: *const @This()) bool {
454 return true;
455 }
456 fn do(s: *@This()) bool {
457 return true;
458 }
459 };
460
461 var s = S{};
462 try expect(S.doC(&s));
463 try expect(s.doC());
464 try expect(S.do(&s));
465 try expect(s.do());
466}
467
468test "implicit cast packed struct field to const ptr" {
469 const LevelUpMove = packed struct {
470 move_id: u9,
471 level: u7,
472
473 fn toInt(value: u7) u7 {
474 return value;
475 }
476 };
477
478 var lup: LevelUpMove = undefined;
479 lup.level = 12;
480 const res = LevelUpMove.toInt(lup.level);
481 try expect(res == 12);
482}
483
484test "pointer to packed struct member in a stack variable" {
485 const S = packed struct {
486 a: u2,
487 b: u2,
488 };
489
490 var s = S{ .a = 2, .b = 0 };
491 var b_ptr = &s.b;
492 try expect(s.b == 0);
493 b_ptr.* = 2;
494 try expect(s.b == 2);
495}
496
497test "non-byte-aligned array inside packed struct" {
498 const Foo = packed struct {
499 a: bool,
500 b: [0x16]u8,
501 };
502 const S = struct {
503 fn bar(slice: []const u8) !void {
504 try expectEqualSlices(u8, slice, "abcdefghijklmnopqurstu");
505 }
506 fn doTheTest() !void {
507 var foo = Foo{
508 .a = true,
509 .b = "abcdefghijklmnopqurstu".*,
510 };
511 const value = foo.b;
512 try bar(&value);
513 }
514 };
515 try S.doTheTest();
516 comptime try S.doTheTest();
517}
518
519test "packed struct with u0 field access" {
520 const S = packed struct {
521 f0: u0,
522 };
523 var s = S{ .f0 = 0 };
524 comptime try expect(s.f0 == 0);
525}
526
527const S0 = struct {
528 bar: S1,
529
530 pub const S1 = struct {
531 value: u8,
532 };
533
534 fn init() @This() {
535 return S0{ .bar = S1{ .value = 123 } };
536 }
537};
538
539var g_foo: S0 = S0.init();
540
541test "access to global struct fields" {
542 g_foo.bar.value = 42;
543 try expect(g_foo.bar.value == 42);
544}
545
546test "packed struct with fp fields" {
547 const S = packed struct {
548 data: [3]f32,
549
550 pub fn frob(self: *@This()) void {
551 self.data[0] += self.data[1] + self.data[2];
552 self.data[1] += self.data[0] + self.data[2];
553 self.data[2] += self.data[0] + self.data[1];
554 }
555 };
556
557 var s: S = undefined;
558 s.data[0] = 1.0;
559 s.data[1] = 2.0;
560 s.data[2] = 3.0;
561 s.frob();
562 try expectEqual(@as(f32, 6.0), s.data[0]);
563 try expectEqual(@as(f32, 11.0), s.data[1]);
564 try expectEqual(@as(f32, 20.0), s.data[2]);
565}
566
567test "use within struct scope" {
568 const S = struct {
569 usingnamespace struct {
570 pub fn inner() i32 {
571 return 42;
572 }
573 };
574 };
575 try expectEqual(@as(i32, 42), S.inner());
576}
577
578test "default struct initialization fields" {
579 const S = struct {
580 a: i32 = 1234,
581 b: i32,
582 };
583 const x = S{
584 .b = 5,
585 };
586 if (x.a + x.b != 1239) {
587 @compileError("it should be comptime known");
588 }
589 var five: i32 = 5;
590 const y = S{
591 .b = five,
592 };
593 try expectEqual(1239, x.a + x.b);
594}
595
596test "fn with C calling convention returns struct by value" {
597 const S = struct {
598 fn entry() !void {
599 var x = makeBar(10);
600 try expectEqual(@as(i32, 10), x.handle);
601 }
602
603 const ExternBar = extern struct {
604 handle: i32,
605 };
606
607 fn makeBar(t: i32) callconv(.C) ExternBar {
608 return ExternBar{
609 .handle = t,
610 };
611 }
612 };
613 try S.entry();
614 comptime try S.entry();
615}
616
617test "for loop over pointers to struct, getting field from struct pointer" {
618 const S = struct {
619 const Foo = struct {
620 name: []const u8,
621 };
622
623 var ok = true;
624
625 fn eql(a: []const u8) bool {
626 return true;
627 }
628
629 const ArrayList = struct {
630 fn toSlice(self: *ArrayList) []*Foo {
631 return @as([*]*Foo, undefined)[0..0];
632 }
633 };
634
635 fn doTheTest() !void {
636 var objects: ArrayList = undefined;
637
638 for (objects.toSlice()) |obj| {
639 if (eql(obj.name)) {
640 ok = false;
641 }
642 }
643
644 try expect(ok);
645 }
646 };
647 try S.doTheTest();
648}
649
650test "zero-bit field in packed struct" {
651 const S = packed struct {
652 x: u10,
653 y: void,
654 };
655 var x: S = undefined;
656}
657
658test "struct field init with catch" {
659 const S = struct {
660 fn doTheTest() !void {
661 var x: anyerror!isize = 1;
662 var req = Foo{
663 .field = x catch undefined,
664 };
665 try expect(req.field == 1);
666 }
667
668 pub const Foo = extern struct {
669 field: isize,
670 };
671 };
672 try S.doTheTest();
673 comptime try S.doTheTest();
674}
675
676test "packed struct with non-ABI-aligned field" {
677 const S = packed struct {
678 x: u9,
679 y: u183,
680 };
681 var s: S = undefined;
682 s.x = 1;
683 s.y = 42;
684 try expect(s.x == 1);
685 try expect(s.y == 42);
686}
687
688test "non-packed struct with u128 entry in union" {
689 const U = union(enum) {
690 Num: u128,
691 Void,
692 };
693
694 const S = struct {
695 f1: U,
696 f2: U,
697 };
698
699 var sx: S = undefined;
700 var s = &sx;
701 try std.testing.expect(@ptrToInt(&s.f2) - @ptrToInt(&s.f1) == @byteOffsetOf(S, "f2"));
702 var v2 = U{ .Num = 123 };
703 s.f2 = v2;
704 try std.testing.expect(s.f2.Num == 123);
705}
706
707test "packed struct field passed to generic function" {
708 const S = struct {
709 const P = packed struct {
710 b: u5,
711 g: u5,
712 r: u5,
713 a: u1,
714 };
715
716 fn genericReadPackedField(ptr: anytype) u5 {
717 return ptr.*;
718 }
719 };
720
721 var p: S.P = undefined;
722 p.b = 29;
723 var loaded = S.genericReadPackedField(&p.b);
724 try expect(loaded == 29);
725}
726
727test "anonymous struct literal syntax" {
728 const S = struct {
729 const Point = struct {
730 x: i32,
731 y: i32,
732 };
733
734 fn doTheTest() !void {
735 var p: Point = .{
736 .x = 1,
737 .y = 2,
738 };
739 try expect(p.x == 1);
740 try expect(p.y == 2);
741 }
742 };
743 try S.doTheTest();
744 comptime try S.doTheTest();
745}
746
747test "fully anonymous struct" {
748 const S = struct {
749 fn doTheTest() !void {
750 try dump(.{
751 .int = @as(u32, 1234),
752 .float = @as(f64, 12.34),
753 .b = true,
754 .s = "hi",
755 });
756 }
757 fn dump(args: anytype) !void {
758 try expect(args.int == 1234);
759 try expect(args.float == 12.34);
760 try expect(args.b);
761 try expect(args.s[0] == 'h');
762 try expect(args.s[1] == 'i');
763 }
764 };
765 try S.doTheTest();
766 comptime try S.doTheTest();
767}
768
769test "fully anonymous list literal" {
770 const S = struct {
771 fn doTheTest() !void {
772 try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" });
773 }
774 fn dump(args: anytype) !void {
775 try expect(args.@"0" == 1234);
776 try expect(args.@"1" == 12.34);
777 try expect(args.@"2");
778 try expect(args.@"3"[0] == 'h');
779 try expect(args.@"3"[1] == 'i');
780 }
781 };
782 try S.doTheTest();
783 comptime try S.doTheTest();
784}
785
786test "anonymous struct literal assigned to variable" {
787 var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) };
788 try expect(vec.@"0" == 22);
789 try expect(vec.@"1" == 55);
790 try expect(vec.@"2" == 99);
791}
792
793test "struct with var field" {
794 const Point = struct {
795 x: anytype,
796 y: anytype,
797 };
798 const pt = Point{
799 .x = 1,
800 .y = 2,
801 };
802 try expect(pt.x == 1);
803 try expect(pt.y == 2);
804}
805
806test "comptime struct field" {
807 const T = struct {
808 a: i32,
809 comptime b: i32 = 1234,
810 };
811
812 var foo: T = undefined;
813 comptime try expect(foo.b == 1234);
814}
815
816test "anon struct literal field value initialized with fn call" {
817 const S = struct {
818 fn doTheTest() !void {
819 var x = .{foo()};
820 try expectEqualSlices(u8, x[0], "hi");
821 }
822 fn foo() []const u8 {
823 return "hi";
824 }
825 };
826 try S.doTheTest();
827 comptime try S.doTheTest();
828}
829
830test "self-referencing struct via array member" {
831 const T = struct {
832 children: [1]*@This(),
833 };
834 var x: T = undefined;
835 x = T{ .children = .{&x} };
836 try expect(x.children[0] == &x);
837}
838
839test "struct with union field" {
840 const Value = struct {
841 ref: u32 = 2,
842 kind: union(enum) {
843 None: usize,
844 Bool: bool,
845 },
846 };
847
848 var True = Value{
849 .kind = .{ .Bool = true },
850 };
851 try expectEqual(@as(u32, 2), True.ref);
852 try expectEqual(true, True.kind.Bool);
853}
854
855test "type coercion of anon struct literal to struct" {
856 const S = struct {
857 const S2 = struct {
858 A: u32,
859 B: []const u8,
860 C: void,
861 D: Foo = .{},
862 };
863
864 const Foo = struct {
865 field: i32 = 1234,
866 };
867
868 fn doTheTest() !void {
869 var y: u32 = 42;
870 const t0 = .{ .A = 123, .B = "foo", .C = {} };
871 const t1 = .{ .A = y, .B = "foo", .C = {} };
872 const y0: S2 = t0;
873 var y1: S2 = t1;
874 try expect(y0.A == 123);
875 try expect(std.mem.eql(u8, y0.B, "foo"));
876 try expect(y0.C == {});
877 try expect(y0.D.field == 1234);
878 try expect(y1.A == y);
879 try expect(std.mem.eql(u8, y1.B, "foo"));
880 try expect(y1.C == {});
881 try expect(y1.D.field == 1234);
882 }
883 };
884 try S.doTheTest();
885 comptime try S.doTheTest();
886}
887
888test "type coercion of pointer to anon struct literal to pointer to struct" {
889 const S = struct {
890 const S2 = struct {
891 A: u32,
892 B: []const u8,
893 C: void,
894 D: Foo = .{},
895 };
896
897 const Foo = struct {
898 field: i32 = 1234,
899 };
900
901 fn doTheTest() !void {
902 var y: u32 = 42;
903 const t0 = &.{ .A = 123, .B = "foo", .C = {} };
904 const t1 = &.{ .A = y, .B = "foo", .C = {} };
905 const y0: *const S2 = t0;
906 var y1: *const S2 = t1;
907 try expect(y0.A == 123);
908 try expect(std.mem.eql(u8, y0.B, "foo"));
909 try expect(y0.C == {});
910 try expect(y0.D.field == 1234);
911 try expect(y1.A == y);
912 try expect(std.mem.eql(u8, y1.B, "foo"));
913 try expect(y1.C == {});
914 try expect(y1.D.field == 1234);
915 }
916 };
917 try S.doTheTest();
918 comptime try S.doTheTest();
919}
920
921test "packed struct with undefined initializers" {
922 const S = struct {
923 const P = packed struct {
924 a: u3,
925 _a: u3 = undefined,
926 b: u3,
927 _b: u3 = undefined,
928 c: u3,
929 _c: u3 = undefined,
930 };
931
932 fn doTheTest() !void {
933 var p: P = undefined;
934 p = P{ .a = 2, .b = 4, .c = 6 };
935 // Make sure the compiler doesn't touch the unprefixed fields.
936 // Use expect since i386-linux doesn't like expectEqual
937 try expect(p.a == 2);
938 try expect(p.b == 4);
939 try expect(p.c == 6);
940 }
941 };
942
943 try S.doTheTest();
944 comptime try S.doTheTest();
945}
test/stage1/behavior/struct_contains_null_ptr_itself.zig deleted-21
...@@ -1,21 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "struct contains null pointer which contains original struct" {
5 var x: ?*NodeLineComment = null;
6 try expect(x == null);
7}
8
9pub const Node = struct {
10 id: Id,
11 comment: ?*NodeLineComment,
12
13 pub const Id = enum {
14 Root,
15 LineComment,
16 };
17};
18
19pub const NodeLineComment = struct {
20 base: Node,
21};
test/stage1/behavior/struct_contains_slice_of_itself.zig deleted-85
...@@ -1,85 +0,0 @@
1const expect = @import("std").testing.expect;
2
3const Node = struct {
4 payload: i32,
5 children: []Node,
6};
7
8const NodeAligned = struct {
9 payload: i32,
10 children: []align(@alignOf(NodeAligned)) NodeAligned,
11};
12
13test "struct contains slice of itself" {
14 var other_nodes = [_]Node{
15 Node{
16 .payload = 31,
17 .children = &[_]Node{},
18 },
19 Node{
20 .payload = 32,
21 .children = &[_]Node{},
22 },
23 };
24 var nodes = [_]Node{
25 Node{
26 .payload = 1,
27 .children = &[_]Node{},
28 },
29 Node{
30 .payload = 2,
31 .children = &[_]Node{},
32 },
33 Node{
34 .payload = 3,
35 .children = other_nodes[0..],
36 },
37 };
38 const root = Node{
39 .payload = 1234,
40 .children = nodes[0..],
41 };
42 try expect(root.payload == 1234);
43 try expect(root.children[0].payload == 1);
44 try expect(root.children[1].payload == 2);
45 try expect(root.children[2].payload == 3);
46 try expect(root.children[2].children[0].payload == 31);
47 try expect(root.children[2].children[1].payload == 32);
48}
49
50test "struct contains aligned slice of itself" {
51 var other_nodes = [_]NodeAligned{
52 NodeAligned{
53 .payload = 31,
54 .children = &[_]NodeAligned{},
55 },
56 NodeAligned{
57 .payload = 32,
58 .children = &[_]NodeAligned{},
59 },
60 };
61 var nodes = [_]NodeAligned{
62 NodeAligned{
63 .payload = 1,
64 .children = &[_]NodeAligned{},
65 },
66 NodeAligned{
67 .payload = 2,
68 .children = &[_]NodeAligned{},
69 },
70 NodeAligned{
71 .payload = 3,
72 .children = other_nodes[0..],
73 },
74 };
75 const root = NodeAligned{
76 .payload = 1234,
77 .children = nodes[0..],
78 };
79 try expect(root.payload == 1234);
80 try expect(root.children[0].payload == 1);
81 try expect(root.children[1].payload == 2);
82 try expect(root.children[2].payload == 3);
83 try expect(root.children[2].children[0].payload == 31);
84 try expect(root.children[2].children[1].payload == 32);
85}
test/stage1/behavior/switch.zig deleted-537
...@@ -1,537 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectError = std.testing.expectError;
4const expectEqual = std.testing.expectEqual;
5
6test "switch with numbers" {
7 try testSwitchWithNumbers(13);
8}
9
10fn testSwitchWithNumbers(x: u32) !void {
11 const result = switch (x) {
12 1, 2, 3, 4...8 => false,
13 13 => true,
14 else => false,
15 };
16 try expect(result);
17}
18
19test "switch with all ranges" {
20 try expect(testSwitchWithAllRanges(50, 3) == 1);
21 try expect(testSwitchWithAllRanges(101, 0) == 2);
22 try expect(testSwitchWithAllRanges(300, 5) == 3);
23 try expect(testSwitchWithAllRanges(301, 6) == 6);
24}
25
26fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
27 return switch (x) {
28 0...100 => 1,
29 101...200 => 2,
30 201...300 => 3,
31 else => y,
32 };
33}
34
35test "implicit comptime switch" {
36 const x = 3 + 4;
37 const result = switch (x) {
38 3 => 10,
39 4 => 11,
40 5, 6 => 12,
41 7, 8 => 13,
42 else => 14,
43 };
44
45 comptime {
46 try expect(result + 1 == 14);
47 }
48}
49
50test "switch on enum" {
51 const fruit = Fruit.Orange;
52 nonConstSwitchOnEnum(fruit);
53}
54const Fruit = enum {
55 Apple,
56 Orange,
57 Banana,
58};
59fn nonConstSwitchOnEnum(fruit: Fruit) void {
60 switch (fruit) {
61 Fruit.Apple => unreachable,
62 Fruit.Orange => {},
63 Fruit.Banana => unreachable,
64 }
65}
66
67test "switch statement" {
68 try nonConstSwitch(SwitchStatmentFoo.C);
69}
70fn nonConstSwitch(foo: SwitchStatmentFoo) !void {
71 const val = switch (foo) {
72 SwitchStatmentFoo.A => @as(i32, 1),
73 SwitchStatmentFoo.B => 2,
74 SwitchStatmentFoo.C => 3,
75 SwitchStatmentFoo.D => 4,
76 };
77 try expect(val == 3);
78}
79const SwitchStatmentFoo = enum {
80 A,
81 B,
82 C,
83 D,
84};
85
86test "switch prong with variable" {
87 try switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
88 try switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
89 try switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} });
90}
91const SwitchProngWithVarEnum = union(enum) {
92 One: i32,
93 Two: f32,
94 Meh: void,
95};
96fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {
97 switch (a) {
98 SwitchProngWithVarEnum.One => |x| {
99 try expect(x == 13);
100 },
101 SwitchProngWithVarEnum.Two => |x| {
102 try expect(x == 13.0);
103 },
104 SwitchProngWithVarEnum.Meh => |x| {
105 const v: void = x;
106 },
107 }
108}
109
110test "switch on enum using pointer capture" {
111 try testSwitchEnumPtrCapture();
112 comptime try testSwitchEnumPtrCapture();
113}
114
115fn testSwitchEnumPtrCapture() !void {
116 var value = SwitchProngWithVarEnum{ .One = 1234 };
117 switch (value) {
118 SwitchProngWithVarEnum.One => |*x| x.* += 1,
119 else => unreachable,
120 }
121 switch (value) {
122 SwitchProngWithVarEnum.One => |x| try expect(x == 1235),
123 else => unreachable,
124 }
125}
126
127test "switch with multiple expressions" {
128 const x = switch (returnsFive()) {
129 1, 2, 3 => 1,
130 4, 5, 6 => 2,
131 else => @as(i32, 3),
132 };
133 try expect(x == 2);
134}
135fn returnsFive() i32 {
136 return 5;
137}
138
139const Number = union(enum) {
140 One: u64,
141 Two: u8,
142 Three: f32,
143};
144
145const number = Number{ .Three = 1.23 };
146
147fn returnsFalse() bool {
148 switch (number) {
149 Number.One => |x| return x > 1234,
150 Number.Two => |x| return x == 'a',
151 Number.Three => |x| return x > 12.34,
152 }
153}
154test "switch on const enum with var" {
155 try expect(!returnsFalse());
156}
157
158test "switch on type" {
159 try expect(trueIfBoolFalseOtherwise(bool));
160 try expect(!trueIfBoolFalseOtherwise(i32));
161}
162
163fn trueIfBoolFalseOtherwise(comptime T: type) bool {
164 return switch (T) {
165 bool => true,
166 else => false,
167 };
168}
169
170test "switch handles all cases of number" {
171 try testSwitchHandleAllCases();
172 comptime try testSwitchHandleAllCases();
173}
174
175fn testSwitchHandleAllCases() !void {
176 try expect(testSwitchHandleAllCasesExhaustive(0) == 3);
177 try expect(testSwitchHandleAllCasesExhaustive(1) == 2);
178 try expect(testSwitchHandleAllCasesExhaustive(2) == 1);
179 try expect(testSwitchHandleAllCasesExhaustive(3) == 0);
180
181 try expect(testSwitchHandleAllCasesRange(100) == 0);
182 try expect(testSwitchHandleAllCasesRange(200) == 1);
183 try expect(testSwitchHandleAllCasesRange(201) == 2);
184 try expect(testSwitchHandleAllCasesRange(202) == 4);
185 try expect(testSwitchHandleAllCasesRange(230) == 3);
186}
187
188fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
189 return switch (x) {
190 0 => @as(u2, 3),
191 1 => 2,
192 2 => 1,
193 3 => 0,
194 };
195}
196
197fn testSwitchHandleAllCasesRange(x: u8) u8 {
198 return switch (x) {
199 0...100 => @as(u8, 0),
200 101...200 => 1,
201 201, 203 => 2,
202 202 => 4,
203 204...255 => 3,
204 };
205}
206
207test "switch all prongs unreachable" {
208 try testAllProngsUnreachable();
209 comptime try testAllProngsUnreachable();
210}
211
212fn testAllProngsUnreachable() !void {
213 try expect(switchWithUnreachable(1) == 2);
214 try expect(switchWithUnreachable(2) == 10);
215}
216
217fn switchWithUnreachable(x: i32) i32 {
218 while (true) {
219 switch (x) {
220 1 => return 2,
221 2 => break,
222 else => continue,
223 }
224 }
225 return 10;
226}
227
228fn return_a_number() anyerror!i32 {
229 return 1;
230}
231
232test "capture value of switch with all unreachable prongs" {
233 const x = return_a_number() catch |err| switch (err) {
234 else => unreachable,
235 };
236 try expect(x == 1);
237}
238
239test "switching on booleans" {
240 try testSwitchOnBools();
241 comptime try testSwitchOnBools();
242}
243
244fn testSwitchOnBools() !void {
245 try expect(testSwitchOnBoolsTrueAndFalse(true) == false);
246 try expect(testSwitchOnBoolsTrueAndFalse(false) == true);
247
248 try expect(testSwitchOnBoolsTrueWithElse(true) == false);
249 try expect(testSwitchOnBoolsTrueWithElse(false) == true);
250
251 try expect(testSwitchOnBoolsFalseWithElse(true) == false);
252 try expect(testSwitchOnBoolsFalseWithElse(false) == true);
253}
254
255fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
256 return switch (x) {
257 true => false,
258 false => true,
259 };
260}
261
262fn testSwitchOnBoolsTrueWithElse(x: bool) bool {
263 return switch (x) {
264 true => false,
265 else => true,
266 };
267}
268
269fn testSwitchOnBoolsFalseWithElse(x: bool) bool {
270 return switch (x) {
271 false => true,
272 else => false,
273 };
274}
275
276test "u0" {
277 var val: u0 = 0;
278 switch (val) {
279 0 => try expect(val == 0),
280 }
281}
282
283test "undefined.u0" {
284 var val: u0 = undefined;
285 switch (val) {
286 0 => try expect(val == 0),
287 }
288}
289
290test "anon enum literal used in switch on union enum" {
291 const Foo = union(enum) {
292 a: i32,
293 };
294
295 var foo = Foo{ .a = 1234 };
296 switch (foo) {
297 .a => |x| {
298 try expect(x == 1234);
299 },
300 }
301}
302
303test "else prong of switch on error set excludes other cases" {
304 const S = struct {
305 fn doTheTest() !void {
306 try expectError(error.C, bar());
307 }
308 const E = error{
309 A,
310 B,
311 } || E2;
312
313 const E2 = error{
314 C,
315 D,
316 };
317
318 fn foo() E!void {
319 return error.C;
320 }
321
322 fn bar() E2!void {
323 foo() catch |err| switch (err) {
324 error.A, error.B => {},
325 else => |e| return e,
326 };
327 }
328 };
329 try S.doTheTest();
330 comptime try S.doTheTest();
331}
332
333test "switch prongs with error set cases make a new error set type for capture value" {
334 const S = struct {
335 fn doTheTest() !void {
336 try expectError(error.B, bar());
337 }
338 const E = E1 || E2;
339
340 const E1 = error{
341 A,
342 B,
343 };
344
345 const E2 = error{
346 C,
347 D,
348 };
349
350 fn foo() E!void {
351 return error.B;
352 }
353
354 fn bar() E1!void {
355 foo() catch |err| switch (err) {
356 error.A, error.B => |e| return e,
357 else => {},
358 };
359 }
360 };
361 try S.doTheTest();
362 comptime try S.doTheTest();
363}
364
365test "return result loc and then switch with range implicit casted to error union" {
366 const S = struct {
367 fn doTheTest() !void {
368 try expect((func(0xb) catch unreachable) == 0xb);
369 }
370 fn func(d: u8) anyerror!u8 {
371 return switch (d) {
372 0xa...0xf => d,
373 else => unreachable,
374 };
375 }
376 };
377 try S.doTheTest();
378 comptime try S.doTheTest();
379}
380
381test "switch with null and T peer types and inferred result location type" {
382 const S = struct {
383 fn doTheTest(c: u8) !void {
384 if (switch (c) {
385 0 => true,
386 else => null,
387 }) |v| {
388 @panic("fail");
389 }
390 }
391 };
392 try S.doTheTest(1);
393 comptime try S.doTheTest(1);
394}
395
396test "switch prongs with cases with identical payload types" {
397 const Union = union(enum) {
398 A: usize,
399 B: isize,
400 C: usize,
401 };
402 const S = struct {
403 fn doTheTest() !void {
404 try doTheSwitch1(Union{ .A = 8 });
405 try doTheSwitch2(Union{ .B = -8 });
406 }
407 fn doTheSwitch1(u: Union) !void {
408 switch (u) {
409 .A, .C => |e| {
410 try expect(@TypeOf(e) == usize);
411 try expect(e == 8);
412 },
413 .B => |e| @panic("fail"),
414 }
415 }
416 fn doTheSwitch2(u: Union) !void {
417 switch (u) {
418 .A, .C => |e| @panic("fail"),
419 .B => |e| {
420 try expect(@TypeOf(e) == isize);
421 try expect(e == -8);
422 },
423 }
424 }
425 };
426 try S.doTheTest();
427 comptime try S.doTheTest();
428}
429
430test "switch with disjoint range" {
431 var q: u8 = 0;
432 switch (q) {
433 0...125 => {},
434 127...255 => {},
435 126...126 => {},
436 }
437}
438
439test "switch variable for range and multiple prongs" {
440 const S = struct {
441 fn doTheTest() !void {
442 var u: u8 = 16;
443 try doTheSwitch(u);
444 comptime try doTheSwitch(u);
445 var v: u8 = 42;
446 try doTheSwitch(v);
447 comptime try doTheSwitch(v);
448 }
449 fn doTheSwitch(q: u8) !void {
450 switch (q) {
451 0...40 => |x| try expect(x == 16),
452 41, 42, 43 => |x| try expect(x == 42),
453 else => try expect(false),
454 }
455 }
456 };
457}
458
459var state: u32 = 0;
460fn poll() void {
461 switch (state) {
462 0 => {
463 state = 1;
464 },
465 else => {
466 state += 1;
467 },
468 }
469}
470
471test "switch on global mutable var isn't constant-folded" {
472 while (state < 2) {
473 poll();
474 }
475}
476
477test "switch on pointer type" {
478 const S = struct {
479 const X = struct {
480 field: u32,
481 };
482
483 const P1 = @intToPtr(*X, 0x400);
484 const P2 = @intToPtr(*X, 0x800);
485 const P3 = @intToPtr(*X, 0xC00);
486
487 fn doTheTest(arg: *X) i32 {
488 switch (arg) {
489 P1 => return 1,
490 P2 => return 2,
491 else => return 3,
492 }
493 }
494 };
495
496 try expect(1 == S.doTheTest(S.P1));
497 try expect(2 == S.doTheTest(S.P2));
498 try expect(3 == S.doTheTest(S.P3));
499 comptime try expect(1 == S.doTheTest(S.P1));
500 comptime try expect(2 == S.doTheTest(S.P2));
501 comptime try expect(3 == S.doTheTest(S.P3));
502}
503
504test "switch on error set with single else" {
505 const S = struct {
506 fn doTheTest() !void {
507 var some: error{Foo} = error.Foo;
508 try expect(switch (some) {
509 else => |a| true,
510 });
511 }
512 };
513
514 try S.doTheTest();
515 comptime try S.doTheTest();
516}
517
518test "while copies its payload" {
519 const S = struct {
520 fn doTheTest() !void {
521 var tmp: union(enum) {
522 A: u8,
523 B: u32,
524 } = .{ .A = 42 };
525 switch (tmp) {
526 .A => |value| {
527 // Modify the original union
528 tmp = .{ .B = 0x10101010 };
529 try expectEqual(@as(u8, 42), value);
530 },
531 else => unreachable,
532 }
533 }
534 };
535 try S.doTheTest();
536 comptime try S.doTheTest();
537}
test/stage1/behavior/switch_prong_err_enum.zig deleted-30
...@@ -1,30 +0,0 @@
1const expect = @import("std").testing.expect;
2
3var read_count: u64 = 0;
4
5fn readOnce() anyerror!u64 {
6 read_count += 1;
7 return read_count;
8}
9
10const FormValue = union(enum) {
11 Address: u64,
12 Other: bool,
13};
14
15fn doThing(form_id: u64) anyerror!FormValue {
16 return switch (form_id) {
17 17 => FormValue{ .Address = try readOnce() },
18 else => error.InvalidDebugInfo,
19 };
20}
21
22test "switch prong returns error enum" {
23 switch (doThing(17) catch unreachable) {
24 FormValue.Address => |payload| {
25 try expect(payload == 1);
26 },
27 else => unreachable,
28 }
29 try expect(read_count == 1);
30}
test/stage1/behavior/switch_prong_implicit_cast.zig deleted-22
...@@ -1,22 +0,0 @@
1const expect = @import("std").testing.expect;
2
3const FormValue = union(enum) {
4 One: void,
5 Two: bool,
6};
7
8fn foo(id: u64) !FormValue {
9 return switch (id) {
10 2 => FormValue{ .Two = true },
11 1 => FormValue{ .One = {} },
12 else => return error.Whatever,
13 };
14}
15
16test "switch prong implicit cast" {
17 const result = switch (foo(2) catch unreachable) {
18 FormValue.One => false,
19 FormValue.Two => |x| x,
20 };
21 try expect(result);
22}
test/stage1/behavior/syntax.zig deleted-68
...@@ -1,68 +0,0 @@
1// Test trailing comma syntax
2// zig fmt: off
3
4extern var a: c_int;
5extern "c" var b: c_int;
6export var c: c_int = 0;
7threadlocal var d: c_int;
8extern threadlocal var e: c_int;
9extern "c" threadlocal var f: c_int;
10export threadlocal var g: c_int = 0;
11
12const struct_trailing_comma = struct { x: i32, y: i32, };
13const struct_no_comma = struct { x: i32, y: i32 };
14const struct_fn_no_comma = struct { fn m() void {} y: i32 };
15
16const enum_no_comma = enum { A, B };
17
18fn container_init() void {
19 const S = struct { x: i32, y: i32 };
20 _ = S { .x = 1, .y = 2 };
21 _ = S { .x = 1, .y = 2, };
22}
23
24fn type_expr_return1() if (true) A {}
25fn type_expr_return2() for (true) |_| A {}
26fn type_expr_return3() while (true) A {}
27fn type_expr_return4() comptime A {}
28
29fn switch_cases(x: i32) void {
30 switch (x) {
31 1,2,3 => {},
32 4,5, => {},
33 6...8, => {},
34 else => {},
35 }
36}
37
38fn switch_prongs(x: i32) void {
39 switch (x) {
40 0 => {},
41 else => {},
42 }
43 switch (x) {
44 0 => {},
45 else => {}
46 }
47}
48
49const fn_no_comma = fn(i32, i32)void;
50const fn_trailing_comma = fn(i32, i32,)void;
51
52fn fn_calls() void {
53 fn add(x: i32, y: i32,) i32 { x + y };
54 _ = add(1, 2);
55 _ = add(1, 2,);
56}
57
58fn asm_lists() void {
59 if (false) { // Build AST but don't analyze
60 asm ("not real assembly"
61 :[a] "x" (x),);
62 asm ("not real assembly"
63 :[a] "x" (->i32),:[a] "x" (1),);
64 asm ("still not real assembly"
65 :::"a","b",);
66 }
67}
68
test/stage1/behavior/this.zig deleted-34
...@@ -1,34 +0,0 @@
1const expect = @import("std").testing.expect;
2
3const module = @This();
4
5fn Point(comptime T: type) type {
6 return struct {
7 const Self = @This();
8 x: T,
9 y: T,
10
11 fn addOne(self: *Self) void {
12 self.x += 1;
13 self.y += 1;
14 }
15 };
16}
17
18fn add(x: i32, y: i32) i32 {
19 return x + y;
20}
21
22test "this refer to module call private fn" {
23 try expect(module.add(1, 2) == 3);
24}
25
26test "this refer to container" {
27 var pt = Point(i32){
28 .x = 12,
29 .y = 34,
30 };
31 pt.addOne();
32 try expect(pt.x == 13);
33 try expect(pt.y == 35);
34}
test/stage1/behavior/translate_c_macros.h deleted-18
...@@ -1,18 +0,0 @@
1// initializer list expression
2typedef struct Color {
3 unsigned char r;
4 unsigned char g;
5 unsigned char b;
6 unsigned char a;
7} Color;
8#define CLITERAL(type) (type)
9#define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray
10
11#define MY_SIZEOF(x) ((int)sizeof(x))
12#define MY_SIZEOF2(x) ((int)sizeof x)
13
14struct Foo {
15 int a;
16};
17
18#define SIZE_OF_FOO sizeof(struct Foo)
test/stage1/behavior/translate_c_macros.zig deleted-22
...@@ -1,22 +0,0 @@
1const expect = @import("std").testing.expect;
2const expectEqual = @import("std").testing.expectEqual;
3
4const h = @cImport(@cInclude("stage1/behavior/translate_c_macros.h"));
5
6test "initializer list expression" {
7 try expectEqual(h.Color{
8 .r = 200,
9 .g = 200,
10 .b = 200,
11 .a = 255,
12 }, h.LIGHTGRAY);
13}
14
15test "sizeof in macros" {
16 try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
17 try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
18}
19
20test "reference to a struct type" {
21 try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);
22}
test/stage1/behavior/truncate.zig deleted-36
...@@ -1,36 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "truncate u0 to larger integer allowed and has comptime known result" {
5 var x: u0 = 0;
6 const y = @truncate(u8, x);
7 comptime try expect(y == 0);
8}
9
10test "truncate.u0.literal" {
11 var z = @truncate(u0, 0);
12 try expect(z == 0);
13}
14
15test "truncate.u0.const" {
16 const c0: usize = 0;
17 var z = @truncate(u0, c0);
18 try expect(z == 0);
19}
20
21test "truncate.u0.var" {
22 var d: u8 = 2;
23 var z = @truncate(u0, d);
24 try expect(z == 0);
25}
26
27test "truncate sign mismatch but comptime known so it works anyway" {
28 const x: u32 = 10;
29 var result = @truncate(i8, x);
30 try expect(result == 10);
31}
32
33test "truncate on comptime integer" {
34 var x = @truncate(u16, 9999);
35 try expect(x == 9999);
36}
test/stage1/behavior/try.zig deleted-43
...@@ -1,43 +0,0 @@
1const expect = @import("std").testing.expect;
2
3test "try on error union" {
4 try tryOnErrorUnionImpl();
5 comptime try 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 => @as(i32, 2),
12 else => unreachable,
13 };
14 try expect(x == 11);
15}
16
17fn returnsTen() anyerror!i32 {
18 return 10;
19}
20
21test "try without vars" {
22 const result1 = if (failIfTrue(true)) 1 else |_| @as(i32, 2);
23 try expect(result1 == 2);
24
25 const result2 = if (failIfTrue(false)) 1 else |_| @as(i32, 2);
26 try expect(result2 == 1);
27}
28
29fn failIfTrue(ok: bool) anyerror!void {
30 if (ok) {
31 return error.ItBroke;
32 } else {
33 return;
34 }
35}
36
37test "try then not executed with assignment" {
38 if (failIfTrue(true)) {
39 unreachable;
40 } else |err| {
41 try expect(err == error.ItBroke);
42 }
43}
test/stage1/behavior/tuple.zig deleted-113
...@@ -1,113 +0,0 @@
1const std = @import("std");
2const testing = std.testing;
3const expect = testing.expect;
4const expectEqual = testing.expectEqual;
5
6test "tuple concatenation" {
7 const S = struct {
8 fn doTheTest() !void {
9 var a: i32 = 1;
10 var b: i32 = 2;
11 var x = .{a};
12 var y = .{b};
13 var c = x ++ y;
14 try expectEqual(@as(i32, 1), c[0]);
15 try expectEqual(@as(i32, 2), c[1]);
16 }
17 };
18 try S.doTheTest();
19 comptime try S.doTheTest();
20}
21
22test "tuple multiplication" {
23 const S = struct {
24 fn doTheTest() !void {
25 {
26 const t = .{} ** 4;
27 try expectEqual(0, @typeInfo(@TypeOf(t)).Struct.fields.len);
28 }
29 {
30 const t = .{'a'} ** 4;
31 try expectEqual(4, @typeInfo(@TypeOf(t)).Struct.fields.len);
32 inline for (t) |x| try expectEqual('a', x);
33 }
34 {
35 const t = .{ 1, 2, 3 } ** 4;
36 try expectEqual(12, @typeInfo(@TypeOf(t)).Struct.fields.len);
37 inline for (t) |x, i| try expectEqual(1 + i % 3, x);
38 }
39 }
40 };
41 try S.doTheTest();
42 comptime try S.doTheTest();
43
44 const T = struct {
45 fn consume_tuple(tuple: anytype, len: usize) !void {
46 try expect(tuple.len == len);
47 }
48
49 fn doTheTest() !void {
50 const t1 = .{};
51
52 var rt_var: u8 = 42;
53 const t2 = .{rt_var} ++ .{};
54
55 try expect(t2.len == 1);
56 try expect(t2.@"0" == rt_var);
57 try expect(t2.@"0" == 42);
58 try expect(&t2.@"0" != &rt_var);
59
60 try consume_tuple(t1 ++ t1, 0);
61 try consume_tuple(.{} ++ .{}, 0);
62 try consume_tuple(.{0} ++ .{}, 1);
63 try consume_tuple(.{0} ++ .{1}, 2);
64 try consume_tuple(.{ 0, 1, 2 } ++ .{ u8, 1, noreturn }, 6);
65 try consume_tuple(t2 ++ t1, 1);
66 try consume_tuple(t1 ++ t2, 1);
67 try consume_tuple(t2 ++ t2, 2);
68 try consume_tuple(.{rt_var} ++ .{}, 1);
69 try consume_tuple(.{rt_var} ++ t1, 1);
70 try consume_tuple(.{} ++ .{rt_var}, 1);
71 try consume_tuple(t2 ++ .{void}, 2);
72 try consume_tuple(t2 ++ .{0}, 2);
73 try consume_tuple(.{0} ++ t2, 2);
74 try consume_tuple(.{void} ++ t2, 2);
75 try consume_tuple(.{u8} ++ .{rt_var} ++ .{true}, 3);
76 }
77 };
78
79 try T.doTheTest();
80 comptime try T.doTheTest();
81}
82
83test "pass tuple to comptime var parameter" {
84 const S = struct {
85 fn Foo(comptime args: anytype) !void {
86 try expect(args[0] == 1);
87 }
88
89 fn doTheTest() !void {
90 try Foo(.{1});
91 }
92 };
93 try S.doTheTest();
94 comptime try S.doTheTest();
95}
96
97test "tuple initializer for var" {
98 const S = struct {
99 fn doTheTest() void {
100 const Bytes = struct {
101 id: usize,
102 };
103
104 var tmp = .{
105 .id = @as(usize, 2),
106 .name = Bytes{ .id = 20 },
107 };
108 }
109 };
110
111 S.doTheTest();
112 comptime S.doTheTest();
113}
test/stage1/behavior/type.zig deleted-454
...@@ -1,454 +0,0 @@
1const builtin = @import("builtin");
2const TypeInfo = builtin.TypeInfo;
3
4const std = @import("std");
5const testing = std.testing;
6
7fn testTypes(comptime types: []const type) !void {
8 inline for (types) |testType| {
9 try testing.expect(testType == @Type(@typeInfo(testType)));
10 }
11}
12
13test "Type.MetaType" {
14 try testing.expect(type == @Type(TypeInfo{ .Type = undefined }));
15 try testTypes(&[_]type{type});
16}
17
18test "Type.Void" {
19 try testing.expect(void == @Type(TypeInfo{ .Void = undefined }));
20 try testTypes(&[_]type{void});
21}
22
23test "Type.Bool" {
24 try testing.expect(bool == @Type(TypeInfo{ .Bool = undefined }));
25 try testTypes(&[_]type{bool});
26}
27
28test "Type.NoReturn" {
29 try testing.expect(noreturn == @Type(TypeInfo{ .NoReturn = undefined }));
30 try testTypes(&[_]type{noreturn});
31}
32
33test "Type.Int" {
34 try testing.expect(u1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .unsigned, .bits = 1 } }));
35 try testing.expect(i1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .signed, .bits = 1 } }));
36 try testing.expect(u8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .unsigned, .bits = 8 } }));
37 try testing.expect(i8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .signed, .bits = 8 } }));
38 try testing.expect(u64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .unsigned, .bits = 64 } }));
39 try testing.expect(i64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .signed, .bits = 64 } }));
40 try testTypes(&[_]type{ u8, u32, i64 });
41}
42
43test "Type.Float" {
44 try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } }));
45 try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } }));
46 try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } }));
47 try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } }));
48 try testTypes(&[_]type{ f16, f32, f64, f128 });
49}
50
51test "Type.Pointer" {
52 try testTypes(&[_]type{
53 // One Value Pointer Types
54 *u8, *const u8,
55 *volatile u8, *const volatile u8,
56 *align(4) u8, *align(4) const u8,
57 *align(4) volatile u8, *align(4) const volatile u8,
58 *align(8) u8, *align(8) const u8,
59 *align(8) volatile u8, *align(8) const volatile u8,
60 *allowzero u8, *allowzero const u8,
61 *allowzero volatile u8, *allowzero const volatile u8,
62 *allowzero align(4) u8, *allowzero align(4) const u8,
63 *allowzero align(4) volatile u8, *allowzero align(4) const volatile u8,
64 // Many Values Pointer Types
65 [*]u8, [*]const u8,
66 [*]volatile u8, [*]const volatile u8,
67 [*]align(4) u8, [*]align(4) const u8,
68 [*]align(4) volatile u8, [*]align(4) const volatile u8,
69 [*]align(8) u8, [*]align(8) const u8,
70 [*]align(8) volatile u8, [*]align(8) const volatile u8,
71 [*]allowzero u8, [*]allowzero const u8,
72 [*]allowzero volatile u8, [*]allowzero const volatile u8,
73 [*]allowzero align(4) u8, [*]allowzero align(4) const u8,
74 [*]allowzero align(4) volatile u8, [*]allowzero align(4) const volatile u8,
75 // Slice Types
76 []u8, []const u8,
77 []volatile u8, []const volatile u8,
78 []align(4) u8, []align(4) const u8,
79 []align(4) volatile u8, []align(4) const volatile u8,
80 []align(8) u8, []align(8) const u8,
81 []align(8) volatile u8, []align(8) const volatile u8,
82 []allowzero u8, []allowzero const u8,
83 []allowzero volatile u8, []allowzero const volatile u8,
84 []allowzero align(4) u8, []allowzero align(4) const u8,
85 []allowzero align(4) volatile u8, []allowzero align(4) const volatile u8,
86 // C Pointer Types
87 [*c]u8, [*c]const u8,
88 [*c]volatile u8, [*c]const volatile u8,
89 [*c]align(4) u8, [*c]align(4) const u8,
90 [*c]align(4) volatile u8, [*c]align(4) const volatile u8,
91 [*c]align(8) u8, [*c]align(8) const u8,
92 [*c]align(8) volatile u8, [*c]align(8) const volatile u8,
93 });
94}
95
96test "Type.Array" {
97 try testing.expect([123]u8 == @Type(TypeInfo{
98 .Array = TypeInfo.Array{
99 .len = 123,
100 .child = u8,
101 .sentinel = null,
102 },
103 }));
104 try testing.expect([2]u32 == @Type(TypeInfo{
105 .Array = TypeInfo.Array{
106 .len = 2,
107 .child = u32,
108 .sentinel = null,
109 },
110 }));
111 try testing.expect([2:0]u32 == @Type(TypeInfo{
112 .Array = TypeInfo.Array{
113 .len = 2,
114 .child = u32,
115 .sentinel = 0,
116 },
117 }));
118 try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool });
119}
120
121test "Type.ComptimeFloat" {
122 try testTypes(&[_]type{comptime_float});
123}
124test "Type.ComptimeInt" {
125 try testTypes(&[_]type{comptime_int});
126}
127test "Type.Undefined" {
128 try testTypes(&[_]type{@TypeOf(undefined)});
129}
130test "Type.Null" {
131 try testTypes(&[_]type{@TypeOf(null)});
132}
133test "@Type create slice with null sentinel" {
134 const Slice = @Type(builtin.TypeInfo{
135 .Pointer = .{
136 .size = .Slice,
137 .is_const = true,
138 .is_volatile = false,
139 .is_allowzero = false,
140 .alignment = 8,
141 .child = *i32,
142 .sentinel = null,
143 },
144 });
145 try testing.expect(Slice == []align(8) const *i32);
146}
147test "@Type picks up the sentinel value from TypeInfo" {
148 try testTypes(&[_]type{
149 [11:0]u8, [4:10]u8,
150 [*:0]u8, [*:0]const u8,
151 [*:0]volatile u8, [*:0]const volatile u8,
152 [*:0]align(4) u8, [*:0]align(4) const u8,
153 [*:0]align(4) volatile u8, [*:0]align(4) const volatile u8,
154 [*:0]align(8) u8, [*:0]align(8) const u8,
155 [*:0]align(8) volatile u8, [*:0]align(8) const volatile u8,
156 [*:0]allowzero u8, [*:0]allowzero const u8,
157 [*:0]allowzero volatile u8, [*:0]allowzero const volatile u8,
158 [*:0]allowzero align(4) u8, [*:0]allowzero align(4) const u8,
159 [*:0]allowzero align(4) volatile u8, [*:0]allowzero align(4) const volatile u8,
160 [*:5]allowzero align(4) volatile u8, [*:5]allowzero align(4) const volatile u8,
161 [:0]u8, [:0]const u8,
162 [:0]volatile u8, [:0]const volatile u8,
163 [:0]align(4) u8, [:0]align(4) const u8,
164 [:0]align(4) volatile u8, [:0]align(4) const volatile u8,
165 [:0]align(8) u8, [:0]align(8) const u8,
166 [:0]align(8) volatile u8, [:0]align(8) const volatile u8,
167 [:0]allowzero u8, [:0]allowzero const u8,
168 [:0]allowzero volatile u8, [:0]allowzero const volatile u8,
169 [:0]allowzero align(4) u8, [:0]allowzero align(4) const u8,
170 [:0]allowzero align(4) volatile u8, [:0]allowzero align(4) const volatile u8,
171 [:4]allowzero align(4) volatile u8, [:4]allowzero align(4) const volatile u8,
172 });
173}
174
175test "Type.Optional" {
176 try testTypes(&[_]type{
177 ?u8,
178 ?*u8,
179 ?[]u8,
180 ?[*]u8,
181 ?[*c]u8,
182 });
183}
184
185test "Type.ErrorUnion" {
186 try testTypes(&[_]type{
187 error{}!void,
188 error{Error}!void,
189 });
190}
191
192test "Type.Opaque" {
193 const Opaque = @Type(.{
194 .Opaque = .{
195 .decls = &[_]TypeInfo.Declaration{},
196 },
197 });
198 try testing.expect(Opaque != opaque {});
199 try testing.expectEqualSlices(
200 TypeInfo.Declaration,
201 &[_]TypeInfo.Declaration{},
202 @typeInfo(Opaque).Opaque.decls,
203 );
204}
205
206test "Type.Vector" {
207 try testTypes(&[_]type{
208 @Vector(0, u8),
209 @Vector(4, u8),
210 @Vector(8, *u8),
211 std.meta.Vector(0, u8),
212 std.meta.Vector(4, u8),
213 std.meta.Vector(8, *u8),
214 });
215}
216
217test "Type.AnyFrame" {
218 try testTypes(&[_]type{
219 anyframe,
220 anyframe->u8,
221 anyframe->anyframe->u8,
222 });
223}
224
225test "Type.EnumLiteral" {
226 try testTypes(&[_]type{
227 @TypeOf(.Dummy),
228 });
229}
230
231fn add(a: i32, b: i32) i32 {
232 return a + b;
233}
234
235test "Type.Frame" {
236 try testTypes(&[_]type{
237 @Frame(add),
238 });
239}
240
241test "Type.ErrorSet" {
242 // error sets don't compare equal so just check if they compile
243 _ = @Type(@typeInfo(error{}));
244 _ = @Type(@typeInfo(error{A}));
245 _ = @Type(@typeInfo(error{ A, B, C }));
246}
247
248test "Type.Struct" {
249 const A = @Type(@typeInfo(struct { x: u8, y: u32 }));
250 const infoA = @typeInfo(A).Struct;
251 try testing.expectEqual(TypeInfo.ContainerLayout.Auto, infoA.layout);
252 try testing.expectEqualSlices(u8, "x", infoA.fields[0].name);
253 try testing.expectEqual(u8, infoA.fields[0].field_type);
254 try testing.expectEqual(@as(?u8, null), infoA.fields[0].default_value);
255 try testing.expectEqualSlices(u8, "y", infoA.fields[1].name);
256 try testing.expectEqual(u32, infoA.fields[1].field_type);
257 try testing.expectEqual(@as(?u32, null), infoA.fields[1].default_value);
258 try testing.expectEqualSlices(TypeInfo.Declaration, &[_]TypeInfo.Declaration{}, infoA.decls);
259 try testing.expectEqual(@as(bool, false), infoA.is_tuple);
260
261 var a = A{ .x = 0, .y = 1 };
262 try testing.expectEqual(@as(u8, 0), a.x);
263 try testing.expectEqual(@as(u32, 1), a.y);
264 a.y += 1;
265 try testing.expectEqual(@as(u32, 2), a.y);
266
267 const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 }));
268 const infoB = @typeInfo(B).Struct;
269 try testing.expectEqual(TypeInfo.ContainerLayout.Extern, infoB.layout);
270 try testing.expectEqualSlices(u8, "x", infoB.fields[0].name);
271 try testing.expectEqual(u8, infoB.fields[0].field_type);
272 try testing.expectEqual(@as(?u8, null), infoB.fields[0].default_value);
273 try testing.expectEqualSlices(u8, "y", infoB.fields[1].name);
274 try testing.expectEqual(u32, infoB.fields[1].field_type);
275 try testing.expectEqual(@as(?u32, 5), infoB.fields[1].default_value);
276 try testing.expectEqual(@as(usize, 0), infoB.decls.len);
277 try testing.expectEqual(@as(bool, false), infoB.is_tuple);
278
279 const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 }));
280 const infoC = @typeInfo(C).Struct;
281 try testing.expectEqual(TypeInfo.ContainerLayout.Packed, infoC.layout);
282 try testing.expectEqualSlices(u8, "x", infoC.fields[0].name);
283 try testing.expectEqual(u8, infoC.fields[0].field_type);
284 try testing.expectEqual(@as(?u8, 3), infoC.fields[0].default_value);
285 try testing.expectEqualSlices(u8, "y", infoC.fields[1].name);
286 try testing.expectEqual(u32, infoC.fields[1].field_type);
287 try testing.expectEqual(@as(?u32, 5), infoC.fields[1].default_value);
288 try testing.expectEqual(@as(usize, 0), infoC.decls.len);
289 try testing.expectEqual(@as(bool, false), infoC.is_tuple);
290}
291
292test "Type.Enum" {
293 const Foo = @Type(.{
294 .Enum = .{
295 .layout = .Auto,
296 .tag_type = u8,
297 .fields = &[_]TypeInfo.EnumField{
298 .{ .name = "a", .value = 1 },
299 .{ .name = "b", .value = 5 },
300 },
301 .decls = &[_]TypeInfo.Declaration{},
302 .is_exhaustive = true,
303 },
304 });
305 try testing.expectEqual(true, @typeInfo(Foo).Enum.is_exhaustive);
306 try testing.expectEqual(@as(u8, 1), @enumToInt(Foo.a));
307 try testing.expectEqual(@as(u8, 5), @enumToInt(Foo.b));
308 const Bar = @Type(.{
309 .Enum = .{
310 .layout = .Extern,
311 .tag_type = u32,
312 .fields = &[_]TypeInfo.EnumField{
313 .{ .name = "a", .value = 1 },
314 .{ .name = "b", .value = 5 },
315 },
316 .decls = &[_]TypeInfo.Declaration{},
317 .is_exhaustive = false,
318 },
319 });
320 try testing.expectEqual(false, @typeInfo(Bar).Enum.is_exhaustive);
321 try testing.expectEqual(@as(u32, 1), @enumToInt(Bar.a));
322 try testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b));
323 try testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6)));
324}
325
326test "Type.Union" {
327 const Untagged = @Type(.{
328 .Union = .{
329 .layout = .Auto,
330 .tag_type = null,
331 .fields = &[_]TypeInfo.UnionField{
332 .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) },
333 .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) },
334 },
335 .decls = &[_]TypeInfo.Declaration{},
336 },
337 });
338 var untagged = Untagged{ .int = 1 };
339 untagged.float = 2.0;
340 untagged.int = 3;
341 try testing.expectEqual(@as(i32, 3), untagged.int);
342
343 const PackedUntagged = @Type(.{
344 .Union = .{
345 .layout = .Packed,
346 .tag_type = null,
347 .fields = &[_]TypeInfo.UnionField{
348 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
349 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
350 },
351 .decls = &[_]TypeInfo.Declaration{},
352 },
353 });
354 var packed_untagged = PackedUntagged{ .signed = -1 };
355 try testing.expectEqual(@as(i32, -1), packed_untagged.signed);
356 try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned);
357
358 const Tag = @Type(.{
359 .Enum = .{
360 .layout = .Auto,
361 .tag_type = u1,
362 .fields = &[_]TypeInfo.EnumField{
363 .{ .name = "signed", .value = 0 },
364 .{ .name = "unsigned", .value = 1 },
365 },
366 .decls = &[_]TypeInfo.Declaration{},
367 .is_exhaustive = true,
368 },
369 });
370 const Tagged = @Type(.{
371 .Union = .{
372 .layout = .Auto,
373 .tag_type = Tag,
374 .fields = &[_]TypeInfo.UnionField{
375 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
376 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
377 },
378 .decls = &[_]TypeInfo.Declaration{},
379 },
380 });
381 var tagged = Tagged{ .signed = -1 };
382 try testing.expectEqual(Tag.signed, tagged);
383 tagged = .{ .unsigned = 1 };
384 try testing.expectEqual(Tag.unsigned, tagged);
385}
386
387test "Type.Union from Type.Enum" {
388 const Tag = @Type(.{
389 .Enum = .{
390 .layout = .Auto,
391 .tag_type = u0,
392 .fields = &[_]TypeInfo.EnumField{
393 .{ .name = "working_as_expected", .value = 0 },
394 },
395 .decls = &[_]TypeInfo.Declaration{},
396 .is_exhaustive = true,
397 },
398 });
399 const T = @Type(.{
400 .Union = .{
401 .layout = .Auto,
402 .tag_type = Tag,
403 .fields = &[_]TypeInfo.UnionField{
404 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
405 },
406 .decls = &[_]TypeInfo.Declaration{},
407 },
408 });
409 _ = T;
410 _ = @typeInfo(T).Union;
411}
412
413test "Type.Union from regular enum" {
414 const E = enum { working_as_expected = 0 };
415 const T = @Type(.{
416 .Union = .{
417 .layout = .Auto,
418 .tag_type = E,
419 .fields = &[_]TypeInfo.UnionField{
420 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
421 },
422 .decls = &[_]TypeInfo.Declaration{},
423 },
424 });
425 _ = T;
426 _ = @typeInfo(T).Union;
427}
428
429test "Type.Fn" {
430 // wasm doesn't support align attributes on functions
431 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
432
433 const foo = struct {
434 fn func(a: usize, b: bool) align(4) callconv(.C) usize {
435 return 0;
436 }
437 }.func;
438 const Foo = @Type(@typeInfo(@TypeOf(foo)));
439 const foo_2: Foo = foo;
440}
441
442test "Type.BoundFn" {
443 // wasm doesn't support align attributes on functions
444 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
445
446 const TestStruct = packed struct {
447 pub fn foo(self: *const @This()) align(4) callconv(.Unspecified) void {}
448 };
449 const test_instance: TestStruct = undefined;
450 try testing.expect(std.meta.eql(
451 @typeName(@TypeOf(test_instance.foo)),
452 @typeName(@Type(@typeInfo(@TypeOf(test_instance.foo)))),
453 ));
454}
test/stage1/behavior/type_info.zig deleted-484
...@@ -1,484 +0,0 @@
1const std = @import("std");
2const builtin = std.builtin;
3const mem = std.mem;
4
5const TypeInfo = builtin.TypeInfo;
6const TypeId = builtin.TypeId;
7
8const expect = std.testing.expect;
9const expectEqualStrings = std.testing.expectEqualStrings;
10
11test "type info: tag type, void info" {
12 try testBasic();
13 comptime try testBasic();
14}
15
16fn testBasic() !void {
17 try expect(@typeInfo(TypeInfo).Union.tag_type == TypeId);
18 const void_info = @typeInfo(void);
19 try expect(void_info == TypeId.Void);
20 try expect(void_info.Void == {});
21}
22
23test "type info: integer, floating point type info" {
24 try testIntFloat();
25 comptime try testIntFloat();
26}
27
28fn testIntFloat() !void {
29 const u8_info = @typeInfo(u8);
30 try expect(u8_info == .Int);
31 try expect(u8_info.Int.signedness == .unsigned);
32 try expect(u8_info.Int.bits == 8);
33
34 const f64_info = @typeInfo(f64);
35 try expect(f64_info == .Float);
36 try expect(f64_info.Float.bits == 64);
37}
38
39test "type info: pointer type info" {
40 try testPointer();
41 comptime try testPointer();
42}
43
44fn testPointer() !void {
45 const u32_ptr_info = @typeInfo(*u32);
46 try expect(u32_ptr_info == .Pointer);
47 try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
48 try expect(u32_ptr_info.Pointer.is_const == false);
49 try expect(u32_ptr_info.Pointer.is_volatile == false);
50 try expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
51 try expect(u32_ptr_info.Pointer.child == u32);
52 try expect(u32_ptr_info.Pointer.sentinel == null);
53}
54
55test "type info: unknown length pointer type info" {
56 try testUnknownLenPtr();
57 comptime try testUnknownLenPtr();
58}
59
60fn testUnknownLenPtr() !void {
61 const u32_ptr_info = @typeInfo([*]const volatile f64);
62 try expect(u32_ptr_info == .Pointer);
63 try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
64 try expect(u32_ptr_info.Pointer.is_const == true);
65 try expect(u32_ptr_info.Pointer.is_volatile == true);
66 try expect(u32_ptr_info.Pointer.sentinel == null);
67 try expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
68 try expect(u32_ptr_info.Pointer.child == f64);
69}
70
71test "type info: null terminated pointer type info" {
72 try testNullTerminatedPtr();
73 comptime try testNullTerminatedPtr();
74}
75
76fn testNullTerminatedPtr() !void {
77 const ptr_info = @typeInfo([*:0]u8);
78 try expect(ptr_info == .Pointer);
79 try expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
80 try expect(ptr_info.Pointer.is_const == false);
81 try expect(ptr_info.Pointer.is_volatile == false);
82 try expect(ptr_info.Pointer.sentinel.? == 0);
83
84 try expect(@typeInfo([:0]u8).Pointer.sentinel != null);
85}
86
87test "type info: C pointer type info" {
88 try testCPtr();
89 comptime try testCPtr();
90}
91
92fn testCPtr() !void {
93 const ptr_info = @typeInfo([*c]align(4) const i8);
94 try expect(ptr_info == .Pointer);
95 try expect(ptr_info.Pointer.size == .C);
96 try expect(ptr_info.Pointer.is_const);
97 try expect(!ptr_info.Pointer.is_volatile);
98 try expect(ptr_info.Pointer.alignment == 4);
99 try expect(ptr_info.Pointer.child == i8);
100}
101
102test "type info: slice type info" {
103 try testSlice();
104 comptime try testSlice();
105}
106
107fn testSlice() !void {
108 const u32_slice_info = @typeInfo([]u32);
109 try expect(u32_slice_info == .Pointer);
110 try expect(u32_slice_info.Pointer.size == .Slice);
111 try expect(u32_slice_info.Pointer.is_const == false);
112 try expect(u32_slice_info.Pointer.is_volatile == false);
113 try expect(u32_slice_info.Pointer.alignment == 4);
114 try expect(u32_slice_info.Pointer.child == u32);
115}
116
117test "type info: array type info" {
118 try testArray();
119 comptime try testArray();
120}
121
122fn testArray() !void {
123 {
124 const info = @typeInfo([42]u8);
125 try expect(info == .Array);
126 try expect(info.Array.len == 42);
127 try expect(info.Array.child == u8);
128 try expect(info.Array.sentinel == null);
129 }
130
131 {
132 const info = @typeInfo([10:0]u8);
133 try expect(info.Array.len == 10);
134 try expect(info.Array.child == u8);
135 try expect(info.Array.sentinel.? == @as(u8, 0));
136 try expect(@sizeOf([10:0]u8) == info.Array.len + 1);
137 }
138}
139
140test "type info: optional type info" {
141 try testOptional();
142 comptime try testOptional();
143}
144
145fn testOptional() !void {
146 const null_info = @typeInfo(?void);
147 try expect(null_info == .Optional);
148 try expect(null_info.Optional.child == void);
149}
150
151test "type info: error set, error union info" {
152 try testErrorSet();
153 comptime try testErrorSet();
154}
155
156fn testErrorSet() !void {
157 const TestErrorSet = error{
158 First,
159 Second,
160 Third,
161 };
162
163 const error_set_info = @typeInfo(TestErrorSet);
164 try expect(error_set_info == .ErrorSet);
165 try expect(error_set_info.ErrorSet.?.len == 3);
166 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "First"));
167
168 const error_union_info = @typeInfo(TestErrorSet!usize);
169 try expect(error_union_info == .ErrorUnion);
170 try expect(error_union_info.ErrorUnion.error_set == TestErrorSet);
171 try expect(error_union_info.ErrorUnion.payload == usize);
172
173 const global_info = @typeInfo(anyerror);
174 try expect(global_info == .ErrorSet);
175 try expect(global_info.ErrorSet == null);
176}
177
178test "type info: enum info" {
179 try testEnum();
180 comptime try testEnum();
181}
182
183fn testEnum() !void {
184 const Os = enum {
185 Windows,
186 Macos,
187 Linux,
188 FreeBSD,
189 };
190
191 const os_info = @typeInfo(Os);
192 try expect(os_info == .Enum);
193 try expect(os_info.Enum.layout == .Auto);
194 try expect(os_info.Enum.fields.len == 4);
195 try expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
196 try expect(os_info.Enum.fields[3].value == 3);
197 try expect(os_info.Enum.tag_type == u2);
198 try expect(os_info.Enum.decls.len == 0);
199}
200
201test "type info: union info" {
202 try testUnion();
203 comptime try testUnion();
204}
205
206fn testUnion() !void {
207 const typeinfo_info = @typeInfo(TypeInfo);
208 try expect(typeinfo_info == .Union);
209 try expect(typeinfo_info.Union.layout == .Auto);
210 try expect(typeinfo_info.Union.tag_type.? == TypeId);
211 try expect(typeinfo_info.Union.fields.len == 25);
212 try expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
213 try expect(typeinfo_info.Union.decls.len == 22);
214
215 const TestNoTagUnion = union {
216 Foo: void,
217 Bar: u32,
218 };
219
220 const notag_union_info = @typeInfo(TestNoTagUnion);
221 try expect(notag_union_info == .Union);
222 try expect(notag_union_info.Union.tag_type == null);
223 try expect(notag_union_info.Union.layout == .Auto);
224 try expect(notag_union_info.Union.fields.len == 2);
225 try expect(notag_union_info.Union.fields[0].alignment == @alignOf(void));
226 try expect(notag_union_info.Union.fields[1].field_type == u32);
227 try expect(notag_union_info.Union.fields[1].alignment == @alignOf(u32));
228
229 const TestExternUnion = extern union {
230 foo: *c_void,
231 };
232
233 const extern_union_info = @typeInfo(TestExternUnion);
234 try expect(extern_union_info.Union.layout == .Extern);
235 try expect(extern_union_info.Union.tag_type == null);
236 try expect(extern_union_info.Union.fields[0].field_type == *c_void);
237}
238
239test "type info: struct info" {
240 try testStruct();
241 comptime try testStruct();
242}
243
244fn testStruct() !void {
245 const unpacked_struct_info = @typeInfo(TestUnpackedStruct);
246 try expect(unpacked_struct_info.Struct.is_tuple == false);
247 try expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32));
248 try expect(unpacked_struct_info.Struct.fields[0].default_value.? == 4);
249 try expectEqualStrings("foobar", unpacked_struct_info.Struct.fields[1].default_value.?);
250
251 const struct_info = @typeInfo(TestStruct);
252 try expect(struct_info == .Struct);
253 try expect(struct_info.Struct.is_tuple == false);
254 try expect(struct_info.Struct.layout == .Packed);
255 try expect(struct_info.Struct.fields.len == 4);
256 try expect(struct_info.Struct.fields[0].alignment == 2 * @alignOf(usize));
257 try expect(struct_info.Struct.fields[2].field_type == *TestStruct);
258 try expect(struct_info.Struct.fields[2].default_value == null);
259 try expect(struct_info.Struct.fields[3].default_value.? == 4);
260 try expect(struct_info.Struct.fields[3].alignment == 1);
261 try expect(struct_info.Struct.decls.len == 2);
262 try expect(struct_info.Struct.decls[0].is_pub);
263 try expect(!struct_info.Struct.decls[0].data.Fn.is_extern);
264 try expect(struct_info.Struct.decls[0].data.Fn.lib_name == null);
265 try expect(struct_info.Struct.decls[0].data.Fn.return_type == void);
266 try expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void);
267}
268
269const TestUnpackedStruct = struct {
270 fieldA: u32 = 4,
271 fieldB: *const [6:0]u8 = "foobar",
272};
273
274const TestStruct = packed struct {
275 fieldA: usize align(2 * @alignOf(usize)),
276 fieldB: void,
277 fieldC: *Self,
278 fieldD: u32 = 4,
279
280 pub fn foo(self: *const Self) void {}
281 const Self = @This();
282};
283
284test "type info: opaque info" {
285 try testOpaque();
286 comptime try testOpaque();
287}
288
289fn testOpaque() !void {
290 const Foo = opaque {
291 const A = 1;
292 fn b() void {}
293 };
294
295 const foo_info = @typeInfo(Foo);
296 try expect(foo_info.Opaque.decls.len == 2);
297}
298
299test "type info: function type info" {
300 // wasm doesn't support align attributes on functions
301 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
302 try testFunction();
303 comptime try testFunction();
304}
305
306fn testFunction() !void {
307 const fn_info = @typeInfo(@TypeOf(foo));
308 try expect(fn_info == .Fn);
309 try expect(fn_info.Fn.alignment > 0);
310 try expect(fn_info.Fn.calling_convention == .C);
311 try expect(!fn_info.Fn.is_generic);
312 try expect(fn_info.Fn.args.len == 2);
313 try expect(fn_info.Fn.is_var_args);
314 try expect(fn_info.Fn.return_type.? == usize);
315 const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));
316 try expect(fn_aligned_info.Fn.alignment == 4);
317
318 const test_instance: TestStruct = undefined;
319 const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));
320 try expect(bound_fn_info == .BoundFn);
321 try expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
322}
323
324extern fn foo(a: usize, b: bool, ...) callconv(.C) usize;
325extern fn fooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;
326
327test "typeInfo with comptime parameter in struct fn def" {
328 const S = struct {
329 pub fn func(comptime x: f32) void {}
330 };
331 comptime var info = @typeInfo(S);
332}
333
334test "type info: vectors" {
335 try testVector();
336 comptime try testVector();
337}
338
339fn testVector() !void {
340 const vec_info = @typeInfo(std.meta.Vector(4, i32));
341 try expect(vec_info == .Vector);
342 try expect(vec_info.Vector.len == 4);
343 try expect(vec_info.Vector.child == i32);
344}
345
346test "type info: anyframe and anyframe->T" {
347 try testAnyFrame();
348 comptime try testAnyFrame();
349}
350
351fn testAnyFrame() !void {
352 {
353 const anyframe_info = @typeInfo(anyframe->i32);
354 try expect(anyframe_info == .AnyFrame);
355 try expect(anyframe_info.AnyFrame.child.? == i32);
356 }
357
358 {
359 const anyframe_info = @typeInfo(anyframe);
360 try expect(anyframe_info == .AnyFrame);
361 try expect(anyframe_info.AnyFrame.child == null);
362 }
363}
364
365test "type info: pass to function" {
366 _ = passTypeInfo(@typeInfo(void));
367 _ = comptime passTypeInfo(@typeInfo(void));
368}
369
370fn passTypeInfo(comptime info: TypeInfo) type {
371 return void;
372}
373
374test "type info: TypeId -> TypeInfo impl cast" {
375 _ = passTypeInfo(TypeId.Void);
376 _ = comptime passTypeInfo(TypeId.Void);
377}
378
379test "type info: extern fns with and without lib names" {
380 const S = struct {
381 extern fn bar1() void;
382 extern "cool" fn bar2() void;
383 };
384 const info = @typeInfo(S);
385 comptime {
386 for (info.Struct.decls) |decl| {
387 if (std.mem.eql(u8, decl.name, "bar1")) {
388 try expect(decl.data.Fn.lib_name == null);
389 } else {
390 try expectEqualStrings("cool", decl.data.Fn.lib_name.?);
391 }
392 }
393 }
394}
395
396test "data field is a compile-time value" {
397 const S = struct {
398 const Bar = @as(isize, -1);
399 };
400 comptime try expect(@typeInfo(S).Struct.decls[0].data.Var == isize);
401}
402
403test "sentinel of opaque pointer type" {
404 const c_void_info = @typeInfo(*c_void);
405 try expect(c_void_info.Pointer.sentinel == null);
406}
407
408test "@typeInfo does not force declarations into existence" {
409 const S = struct {
410 x: i32,
411
412 fn doNotReferenceMe() void {
413 @compileError("test failed");
414 }
415 };
416 comptime try expect(@typeInfo(S).Struct.fields.len == 1);
417}
418
419test "defaut value for a var-typed field" {
420 const S = struct { x: anytype };
421 try expect(@typeInfo(S).Struct.fields[0].default_value == null);
422}
423
424fn add(a: i32, b: i32) i32 {
425 return a + b;
426}
427
428test "type info for async frames" {
429 switch (@typeInfo(@Frame(add))) {
430 .Frame => |frame| {
431 try expect(frame.function == add);
432 },
433 else => unreachable,
434 }
435}
436
437test "type info: value is correctly copied" {
438 comptime {
439 var ptrInfo = @typeInfo([]u32);
440 ptrInfo.Pointer.size = .One;
441 try expect(@typeInfo([]u32).Pointer.size == .Slice);
442 }
443}
444
445test "Declarations are returned in declaration order" {
446 const S = struct {
447 const a = 1;
448 const b = 2;
449 const c = 3;
450 const d = 4;
451 const e = 5;
452 };
453 const d = @typeInfo(S).Struct.decls;
454 try expect(std.mem.eql(u8, d[0].name, "a"));
455 try expect(std.mem.eql(u8, d[1].name, "b"));
456 try expect(std.mem.eql(u8, d[2].name, "c"));
457 try expect(std.mem.eql(u8, d[3].name, "d"));
458 try expect(std.mem.eql(u8, d[4].name, "e"));
459}
460
461test "Struct.is_tuple" {
462 try expect(@typeInfo(@TypeOf(.{0})).Struct.is_tuple);
463 try expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);
464}
465
466test "StructField.is_comptime" {
467 const info = @typeInfo(struct { x: u8 = 3, comptime y: u32 = 5 }).Struct;
468 try expect(!info.fields[0].is_comptime);
469 try expect(info.fields[1].is_comptime);
470}
471
472test "typeInfo resolves usingnamespace declarations" {
473 const A = struct {
474 pub const f1 = 42;
475 };
476
477 const B = struct {
478 const f0 = 42;
479 usingnamespace A;
480 };
481
482 try expect(@typeInfo(B).Struct.decls.len == 2);
483 //a
484}
test/stage1/behavior/typename.zig deleted-7
...@@ -1,7 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
4
5test "slice" {
6 try expectEqualSlices(u8, "[]u8", @typeName([]u8));
7}
test/stage1/behavior/undefined.zig deleted-69
...@@ -1,69 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4
5fn initStaticArray() [10]i32 {
6 var array: [10]i32 = undefined;
7 array[0] = 1;
8 array[4] = 2;
9 array[7] = 3;
10 array[9] = 4;
11 return array;
12}
13const static_array = initStaticArray();
14test "init static array to undefined" {
15 try expect(static_array[0] == 1);
16 try expect(static_array[4] == 2);
17 try expect(static_array[7] == 3);
18 try expect(static_array[9] == 4);
19
20 comptime {
21 try expect(static_array[0] == 1);
22 try expect(static_array[4] == 2);
23 try expect(static_array[7] == 3);
24 try expect(static_array[9] == 4);
25 }
26}
27
28const Foo = struct {
29 x: i32,
30
31 fn setFooXMethod(foo: *Foo) void {
32 foo.x = 3;
33 }
34};
35
36fn setFooX(foo: *Foo) void {
37 foo.x = 2;
38}
39
40test "assign undefined to struct" {
41 comptime {
42 var foo: Foo = undefined;
43 setFooX(&foo);
44 try expect(foo.x == 2);
45 }
46 {
47 var foo: Foo = undefined;
48 setFooX(&foo);
49 try expect(foo.x == 2);
50 }
51}
52
53test "assign undefined to struct with method" {
54 comptime {
55 var foo: Foo = undefined;
56 foo.setFooXMethod();
57 try expect(foo.x == 3);
58 }
59 {
60 var foo: Foo = undefined;
61 foo.setFooXMethod();
62 try expect(foo.x == 3);
63 }
64}
65
66test "type name of undefined" {
67 const x = undefined;
68 try expect(mem.eql(u8, @typeName(@TypeOf(x)), "(undefined)"));
69}
test/stage1/behavior/underscore.zig deleted-28
...@@ -1,28 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "ignore lval with underscore" {
5 _ = false;
6}
7
8test "ignore lval with underscore (for loop)" {
9 for ([_]void{}) |_, i| {
10 for ([_]void{}) |_, j| {
11 break;
12 }
13 break;
14 }
15}
16
17test "ignore lval with underscore (while loop)" {
18 while (optionalReturnError()) |_| {
19 while (optionalReturnError()) |_| {
20 break;
21 } else |_| {}
22 break;
23 } else |_| {}
24}
25
26fn optionalReturnError() !?u32 {
27 return error.optionalReturnError;
28}
test/stage1/behavior/union.zig deleted-806
...@@ -1,806 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const Tag = std.meta.Tag;
5
6const Value = union(enum) {
7 Int: u64,
8 Array: [9]u8,
9};
10
11const Agg = struct {
12 val1: Value,
13 val2: Value,
14};
15
16const v1 = Value{ .Int = 1234 };
17const v2 = Value{ .Array = [_]u8{3} ** 9 };
18
19const err = @as(anyerror!Agg, Agg{
20 .val1 = v1,
21 .val2 = v2,
22});
23
24const array = [_]Value{
25 v1,
26 v2,
27 v1,
28 v2,
29};
30
31test "unions embedded in aggregate types" {
32 switch (array[1]) {
33 Value.Array => |arr| try expect(arr[4] == 3),
34 else => unreachable,
35 }
36 switch ((err catch unreachable).val1) {
37 Value.Int => |x| try expect(x == 1234),
38 else => unreachable,
39 }
40}
41
42const Foo = union {
43 float: f64,
44 int: i32,
45};
46
47test "basic unions" {
48 var foo = Foo{ .int = 1 };
49 try expect(foo.int == 1);
50 foo = Foo{ .float = 12.34 };
51 try expect(foo.float == 12.34);
52}
53
54test "comptime union field access" {
55 comptime {
56 var foo = Foo{ .int = 0 };
57 try expect(foo.int == 0);
58
59 foo = Foo{ .float = 42.42 };
60 try expect(foo.float == 42.42);
61 }
62}
63
64test "init union with runtime value" {
65 var foo: Foo = undefined;
66
67 setFloat(&foo, 12.34);
68 try expect(foo.float == 12.34);
69
70 setInt(&foo, 42);
71 try expect(foo.int == 42);
72}
73
74fn setFloat(foo: *Foo, x: f64) void {
75 foo.* = Foo{ .float = x };
76}
77
78fn setInt(foo: *Foo, x: i32) void {
79 foo.* = Foo{ .int = x };
80}
81
82const FooExtern = extern union {
83 float: f64,
84 int: i32,
85};
86
87test "basic extern unions" {
88 var foo = FooExtern{ .int = 1 };
89 try expect(foo.int == 1);
90 foo.float = 12.34;
91 try expect(foo.float == 12.34);
92}
93
94const Letter = enum {
95 A,
96 B,
97 C,
98};
99const Payload = union(Letter) {
100 A: i32,
101 B: f64,
102 C: bool,
103};
104
105test "union with specified enum tag" {
106 try doTest();
107 comptime try doTest();
108}
109
110fn doTest() !void {
111 try expect((try bar(Payload{ .A = 1234 })) == -10);
112}
113
114fn bar(value: Payload) !i32 {
115 try expect(@as(Letter, value) == Letter.A);
116 return switch (value) {
117 Payload.A => |x| return x - 1244,
118 Payload.B => |x| if (x == 12.34) @as(i32, 20) else 21,
119 Payload.C => |x| if (x) @as(i32, 30) else 31,
120 };
121}
122
123const MultipleChoice = union(enum(u32)) {
124 A = 20,
125 B = 40,
126 C = 60,
127 D = 1000,
128};
129test "simple union(enum(u32))" {
130 var x = MultipleChoice.C;
131 try expect(x == MultipleChoice.C);
132 try expect(@enumToInt(@as(Tag(MultipleChoice), x)) == 60);
133}
134
135const MultipleChoice2 = union(enum(u32)) {
136 Unspecified1: i32,
137 A: f32 = 20,
138 Unspecified2: void,
139 B: bool = 40,
140 Unspecified3: i32,
141 C: i8 = 60,
142 Unspecified4: void,
143 D: void = 1000,
144 Unspecified5: i32,
145};
146
147test "union(enum(u32)) with specified and unspecified tag values" {
148 comptime try expect(Tag(Tag(MultipleChoice2)) == u32);
149 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
150 comptime try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
151}
152
153fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void {
154 try expect(@enumToInt(@as(Tag(MultipleChoice2), x)) == 60);
155 try expect(1123 == switch (x) {
156 MultipleChoice2.A => 1,
157 MultipleChoice2.B => 2,
158 MultipleChoice2.C => |v| @as(i32, 1000) + v,
159 MultipleChoice2.D => 4,
160 MultipleChoice2.Unspecified1 => 5,
161 MultipleChoice2.Unspecified2 => 6,
162 MultipleChoice2.Unspecified3 => 7,
163 MultipleChoice2.Unspecified4 => 8,
164 MultipleChoice2.Unspecified5 => 9,
165 });
166}
167
168const ExternPtrOrInt = extern union {
169 ptr: *u8,
170 int: u64,
171};
172test "extern union size" {
173 comptime try expect(@sizeOf(ExternPtrOrInt) == 8);
174}
175
176const PackedPtrOrInt = packed union {
177 ptr: *u8,
178 int: u64,
179};
180test "extern union size" {
181 comptime try expect(@sizeOf(PackedPtrOrInt) == 8);
182}
183
184const ZeroBits = union {
185 OnlyField: void,
186};
187test "union with only 1 field which is void should be zero bits" {
188 comptime try expect(@sizeOf(ZeroBits) == 0);
189}
190
191const TheTag = enum {
192 A,
193 B,
194 C,
195};
196const TheUnion = union(TheTag) {
197 A: i32,
198 B: i32,
199 C: i32,
200};
201test "union field access gives the enum values" {
202 try expect(TheUnion.A == TheTag.A);
203 try expect(TheUnion.B == TheTag.B);
204 try expect(TheUnion.C == TheTag.C);
205}
206
207test "cast union to tag type of union" {
208 try testCastUnionToTag(TheUnion{ .B = 1234 });
209 comptime try testCastUnionToTag(TheUnion{ .B = 1234 });
210}
211
212fn testCastUnionToTag(x: TheUnion) !void {
213 try expect(@as(TheTag, x) == TheTag.B);
214}
215
216test "cast tag type of union to union" {
217 var x: Value2 = Letter2.B;
218 try expect(@as(Letter2, x) == Letter2.B);
219}
220const Letter2 = enum {
221 A,
222 B,
223 C,
224};
225const Value2 = union(Letter2) {
226 A: i32,
227 B,
228 C,
229};
230
231test "implicit cast union to its tag type" {
232 var x: Value2 = Letter2.B;
233 try expect(x == Letter2.B);
234 try giveMeLetterB(x);
235}
236fn giveMeLetterB(x: Letter2) !void {
237 try expect(x == Value2.B);
238}
239
240pub const PackThis = union(enum) {
241 Invalid: bool,
242 StringLiteral: u2,
243};
244
245test "constant packed union" {
246 try testConstPackedUnion(&[_]PackThis{PackThis{ .StringLiteral = 1 }});
247}
248
249fn testConstPackedUnion(expected_tokens: []const PackThis) !void {
250 try expect(expected_tokens[0].StringLiteral == 1);
251}
252
253test "switch on union with only 1 field" {
254 var r: PartialInst = undefined;
255 r = PartialInst.Compiled;
256 switch (r) {
257 PartialInst.Compiled => {
258 var z: PartialInstWithPayload = undefined;
259 z = PartialInstWithPayload{ .Compiled = 1234 };
260 switch (z) {
261 PartialInstWithPayload.Compiled => |x| {
262 try expect(x == 1234);
263 return;
264 },
265 }
266 },
267 }
268 unreachable;
269}
270
271const PartialInst = union(enum) {
272 Compiled,
273};
274
275const PartialInstWithPayload = union(enum) {
276 Compiled: i32,
277};
278
279test "access a member of tagged union with conflicting enum tag name" {
280 const Bar = union(enum) {
281 A: A,
282 B: B,
283
284 const A = u8;
285 const B = void;
286 };
287
288 comptime try expect(Bar.A == u8);
289}
290
291test "tagged union initialization with runtime void" {
292 try expect(testTaggedUnionInit({}));
293}
294
295const TaggedUnionWithAVoid = union(enum) {
296 A,
297 B: i32,
298};
299
300fn testTaggedUnionInit(x: anytype) bool {
301 const y = TaggedUnionWithAVoid{ .A = x };
302 return @as(Tag(TaggedUnionWithAVoid), y) == TaggedUnionWithAVoid.A;
303}
304
305pub const UnionEnumNoPayloads = union(enum) {
306 A,
307 B,
308};
309
310test "tagged union with no payloads" {
311 const a = UnionEnumNoPayloads{ .B = {} };
312 switch (a) {
313 Tag(UnionEnumNoPayloads).A => @panic("wrong"),
314 Tag(UnionEnumNoPayloads).B => {},
315 }
316}
317
318test "union with only 1 field casted to its enum type" {
319 const Literal = union(enum) {
320 Number: f64,
321 Bool: bool,
322 };
323
324 const Expr = union(enum) {
325 Literal: Literal,
326 };
327
328 var e = Expr{ .Literal = Literal{ .Bool = true } };
329 const ExprTag = Tag(Expr);
330 comptime try expect(Tag(ExprTag) == u0);
331 var t = @as(ExprTag, e);
332 try expect(t == Expr.Literal);
333}
334
335test "union with only 1 field casted to its enum type which has enum value specified" {
336 const Literal = union(enum) {
337 Number: f64,
338 Bool: bool,
339 };
340
341 const ExprTag = enum(comptime_int) {
342 Literal = 33,
343 };
344
345 const Expr = union(ExprTag) {
346 Literal: Literal,
347 };
348
349 var e = Expr{ .Literal = Literal{ .Bool = true } };
350 comptime try expect(Tag(ExprTag) == comptime_int);
351 var t = @as(ExprTag, e);
352 try expect(t == Expr.Literal);
353 try expect(@enumToInt(t) == 33);
354 comptime try expect(@enumToInt(t) == 33);
355}
356
357test "@enumToInt works on unions" {
358 const Bar = union(enum) {
359 A: bool,
360 B: u8,
361 C,
362 };
363
364 const a = Bar{ .A = true };
365 var b = Bar{ .B = undefined };
366 var c = Bar.C;
367 try expect(@enumToInt(a) == 0);
368 try expect(@enumToInt(b) == 1);
369 try expect(@enumToInt(c) == 2);
370}
371
372const Attribute = union(enum) {
373 A: bool,
374 B: u8,
375};
376
377fn setAttribute(attr: Attribute) void {}
378
379fn Setter(attr: Attribute) type {
380 return struct {
381 fn set() void {
382 setAttribute(attr);
383 }
384 };
385}
386
387test "comptime union field value equality" {
388 const a0 = Setter(Attribute{ .A = false });
389 const a1 = Setter(Attribute{ .A = true });
390 const a2 = Setter(Attribute{ .A = false });
391
392 const b0 = Setter(Attribute{ .B = 5 });
393 const b1 = Setter(Attribute{ .B = 9 });
394 const b2 = Setter(Attribute{ .B = 5 });
395
396 try expect(a0 == a0);
397 try expect(a1 == a1);
398 try expect(a0 == a2);
399
400 try expect(b0 == b0);
401 try expect(b1 == b1);
402 try expect(b0 == b2);
403
404 try expect(a0 != b0);
405 try expect(a0 != a1);
406 try expect(b0 != b1);
407}
408
409test "return union init with void payload" {
410 const S = struct {
411 fn entry() !void {
412 try expect(func().state == State.one);
413 }
414 const Outer = union(enum) {
415 state: State,
416 };
417 const State = union(enum) {
418 one: void,
419 two: u32,
420 };
421 fn func() Outer {
422 return Outer{ .state = State{ .one = {} } };
423 }
424 };
425 try S.entry();
426 comptime try S.entry();
427}
428
429test "@unionInit can modify a union type" {
430 const UnionInitEnum = union(enum) {
431 Boolean: bool,
432 Byte: u8,
433 };
434
435 var value: UnionInitEnum = undefined;
436
437 value = @unionInit(UnionInitEnum, "Boolean", true);
438 try expect(value.Boolean == true);
439 value.Boolean = false;
440 try expect(value.Boolean == false);
441
442 value = @unionInit(UnionInitEnum, "Byte", 2);
443 try expect(value.Byte == 2);
444 value.Byte = 3;
445 try expect(value.Byte == 3);
446}
447
448test "@unionInit can modify a pointer value" {
449 const UnionInitEnum = union(enum) {
450 Boolean: bool,
451 Byte: u8,
452 };
453
454 var value: UnionInitEnum = undefined;
455 var value_ptr = &value;
456
457 value_ptr.* = @unionInit(UnionInitEnum, "Boolean", true);
458 try expect(value.Boolean == true);
459
460 value_ptr.* = @unionInit(UnionInitEnum, "Byte", 2);
461 try expect(value.Byte == 2);
462}
463
464test "union no tag with struct member" {
465 const Struct = struct {};
466 const Union = union {
467 s: Struct,
468 pub fn foo(self: *@This()) void {}
469 };
470 var u = Union{ .s = Struct{} };
471 u.foo();
472}
473
474fn testComparison() !void {
475 var x = Payload{ .A = 42 };
476 try expect(x == .A);
477 try expect(x != .B);
478 try expect(x != .C);
479 try expect((x == .B) == false);
480 try expect((x == .C) == false);
481 try expect((x != .A) == false);
482}
483
484test "comparison between union and enum literal" {
485 try testComparison();
486 comptime try testComparison();
487}
488
489test "packed union generates correctly aligned LLVM type" {
490 const U = packed union {
491 f1: fn () error{TestUnexpectedResult}!void,
492 f2: u32,
493 };
494 var foo = [_]U{
495 U{ .f1 = doTest },
496 U{ .f2 = 0 },
497 };
498 try foo[0].f1();
499}
500
501test "union with one member defaults to u0 tag type" {
502 const U0 = union(enum) {
503 X: u32,
504 };
505 comptime try expect(Tag(Tag(U0)) == u0);
506}
507
508test "union with comptime_int tag" {
509 const Union = union(enum(comptime_int)) {
510 X: u32,
511 Y: u16,
512 Z: u8,
513 };
514 comptime try expect(Tag(Tag(Union)) == comptime_int);
515}
516
517test "extern union doesn't trigger field check at comptime" {
518 const U = extern union {
519 x: u32,
520 y: u8,
521 };
522
523 const x = U{ .x = 0x55AAAA55 };
524 comptime try expect(x.y == 0x55);
525}
526
527const Foo1 = union(enum) {
528 f: struct {
529 x: usize,
530 },
531};
532var glbl: Foo1 = undefined;
533
534test "global union with single field is correctly initialized" {
535 glbl = Foo1{
536 .f = @typeInfo(Foo1).Union.fields[0].field_type{ .x = 123 },
537 };
538 try expect(glbl.f.x == 123);
539}
540
541pub const FooUnion = union(enum) {
542 U0: usize,
543 U1: u8,
544};
545
546var glbl_array: [2]FooUnion = undefined;
547
548test "initialize global array of union" {
549 glbl_array[1] = FooUnion{ .U1 = 2 };
550 glbl_array[0] = FooUnion{ .U0 = 1 };
551 try expect(glbl_array[0].U0 == 1);
552 try expect(glbl_array[1].U1 == 2);
553}
554
555test "anonymous union literal syntax" {
556 const S = struct {
557 const Number = union {
558 int: i32,
559 float: f64,
560 };
561
562 fn doTheTest() !void {
563 var i: Number = .{ .int = 42 };
564 var f = makeNumber();
565 try expect(i.int == 42);
566 try expect(f.float == 12.34);
567 }
568
569 fn makeNumber() Number {
570 return .{ .float = 12.34 };
571 }
572 };
573 try S.doTheTest();
574 comptime try S.doTheTest();
575}
576
577test "update the tag value for zero-sized unions" {
578 const S = union(enum) {
579 U0: void,
580 U1: void,
581 };
582 var x = S{ .U0 = {} };
583 try expect(x == .U0);
584 x = S{ .U1 = {} };
585 try expect(x == .U1);
586}
587
588test "function call result coerces from tagged union to the tag" {
589 const S = struct {
590 const Arch = union(enum) {
591 One,
592 Two: usize,
593 };
594
595 const ArchTag = Tag(Arch);
596
597 fn doTheTest() !void {
598 var x: ArchTag = getArch1();
599 try expect(x == .One);
600
601 var y: ArchTag = getArch2();
602 try expect(y == .Two);
603 }
604
605 pub fn getArch1() Arch {
606 return .One;
607 }
608
609 pub fn getArch2() Arch {
610 return .{ .Two = 99 };
611 }
612 };
613 try S.doTheTest();
614 comptime try S.doTheTest();
615}
616
617test "0-sized extern union definition" {
618 const U = extern union {
619 a: void,
620 const f = 1;
621 };
622
623 try expect(U.f == 1);
624}
625
626test "union initializer generates padding only if needed" {
627 const U = union(enum) {
628 A: u24,
629 };
630
631 var v = U{ .A = 532 };
632 try expect(v.A == 532);
633}
634
635test "runtime tag name with single field" {
636 const U = union(enum) {
637 A: i32,
638 };
639
640 var v = U{ .A = 42 };
641 try expect(std.mem.eql(u8, @tagName(v), "A"));
642}
643
644test "cast from anonymous struct to union" {
645 const S = struct {
646 const U = union(enum) {
647 A: u32,
648 B: []const u8,
649 C: void,
650 };
651 fn doTheTest() !void {
652 var y: u32 = 42;
653 const t0 = .{ .A = 123 };
654 const t1 = .{ .B = "foo" };
655 const t2 = .{ .C = {} };
656 const t3 = .{ .A = y };
657 const x0: U = t0;
658 var x1: U = t1;
659 const x2: U = t2;
660 var x3: U = t3;
661 try expect(x0.A == 123);
662 try expect(std.mem.eql(u8, x1.B, "foo"));
663 try expect(x2 == .C);
664 try expect(x3.A == y);
665 }
666 };
667 try S.doTheTest();
668 comptime try S.doTheTest();
669}
670
671test "cast from pointer to anonymous struct to pointer to union" {
672 const S = struct {
673 const U = union(enum) {
674 A: u32,
675 B: []const u8,
676 C: void,
677 };
678 fn doTheTest() !void {
679 var y: u32 = 42;
680 const t0 = &.{ .A = 123 };
681 const t1 = &.{ .B = "foo" };
682 const t2 = &.{ .C = {} };
683 const t3 = &.{ .A = y };
684 const x0: *const U = t0;
685 var x1: *const U = t1;
686 const x2: *const U = t2;
687 var x3: *const U = t3;
688 try expect(x0.A == 123);
689 try expect(std.mem.eql(u8, x1.B, "foo"));
690 try expect(x2.* == .C);
691 try expect(x3.A == y);
692 }
693 };
694 try S.doTheTest();
695 comptime try S.doTheTest();
696}
697
698test "method call on an empty union" {
699 const S = struct {
700 const MyUnion = union(MyUnionTag) {
701 pub const MyUnionTag = enum { X1, X2 };
702 X1: [0]u8,
703 X2: [0]u8,
704
705 pub fn useIt(self: *@This()) bool {
706 return true;
707 }
708 };
709
710 fn doTheTest() !void {
711 var u = MyUnion{ .X1 = [0]u8{} };
712 try expect(u.useIt());
713 }
714 };
715 try S.doTheTest();
716 comptime try S.doTheTest();
717}
718
719test "switching on non exhaustive union" {
720 const S = struct {
721 const E = enum(u8) {
722 a,
723 b,
724 _,
725 };
726 const U = union(E) {
727 a: i32,
728 b: u32,
729 };
730 fn doTheTest() !void {
731 var a = U{ .a = 2 };
732 switch (a) {
733 .a => |val| try expect(val == 2),
734 .b => unreachable,
735 }
736 }
737 };
738 try S.doTheTest();
739 comptime try S.doTheTest();
740}
741
742test "containers with single-field enums" {
743 const S = struct {
744 const A = union(enum) { f1 };
745 const B = union(enum) { f1: void };
746 const C = struct { a: A };
747 const D = struct { a: B };
748
749 fn doTheTest() !void {
750 var array1 = [1]A{A{ .f1 = {} }};
751 var array2 = [1]B{B{ .f1 = {} }};
752 try expect(array1[0] == .f1);
753 try expect(array2[0] == .f1);
754
755 var struct1 = C{ .a = A{ .f1 = {} } };
756 var struct2 = D{ .a = B{ .f1 = {} } };
757 try expect(struct1.a == .f1);
758 try expect(struct2.a == .f1);
759 }
760 };
761
762 try S.doTheTest();
763 comptime try S.doTheTest();
764}
765
766test "@unionInit on union w/ tag but no fields" {
767 const S = struct {
768 const Type = enum(u8) { no_op = 105 };
769
770 const Data = union(Type) {
771 no_op: void,
772
773 pub fn decode(buf: []const u8) Data {
774 return @unionInit(Data, "no_op", {});
775 }
776 };
777
778 comptime {
779 try expect(@sizeOf(Data) != 0);
780 }
781
782 fn doTheTest() !void {
783 var data: Data = .{ .no_op = .{} };
784 var o = Data.decode(&[_]u8{});
785 try expectEqual(Type.no_op, o);
786 }
787 };
788
789 try S.doTheTest();
790 comptime try S.doTheTest();
791}
792
793test "union enum type gets a separate scope" {
794 const S = struct {
795 const U = union(enum) {
796 a: u8,
797 const foo = 1;
798 };
799
800 fn doTheTest() !void {
801 try expect(!@hasDecl(Tag(U), "foo"));
802 }
803 };
804
805 try S.doTheTest();
806}
test/stage1/behavior/usingnamespace.zig deleted-22
...@@ -1,22 +0,0 @@
1const std = @import("std");
2
3fn Foo(comptime T: type) type {
4 return struct {
5 usingnamespace T;
6 };
7}
8
9test "usingnamespace inside a generic struct" {
10 const std2 = Foo(std);
11 const testing2 = Foo(std.testing);
12 try std2.testing.expect(true);
13 try testing2.expect(true);
14}
15
16usingnamespace struct {
17 pub const foo = 42;
18};
19
20test "usingnamespace does not redeclare an imported variable" {
21 comptime try std.testing.expect(foo == 42);
22}
test/stage1/behavior/var_args.zig deleted-83
...@@ -1,83 +0,0 @@
1const expect = @import("std").testing.expect;
2
3fn add(args: anytype) i32 {
4 var sum = @as(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 try expect(add(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
16 try expect(add(.{@as(i32, 1234)}) == 1234);
17 try expect(add(.{}) == 0);
18}
19
20fn readFirstVarArg(args: anytype) void {
21 const value = args[0];
22}
23
24test "send void arg to var args" {
25 readFirstVarArg(.{{}});
26}
27
28test "pass args directly" {
29 try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
30 try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234);
31 try expect(addSomeStuff(.{}) == 0);
32}
33
34fn addSomeStuff(args: anytype) i32 {
35 return add(args);
36}
37
38test "runtime parameter before var args" {
39 try expect((try extraFn(10, .{})) == 0);
40 try expect((try extraFn(10, .{false})) == 1);
41 try expect((try extraFn(10, .{ false, true })) == 2);
42
43 comptime {
44 try expect((try extraFn(10, .{})) == 0);
45 try expect((try extraFn(10, .{false})) == 1);
46 try expect((try extraFn(10, .{ false, true })) == 2);
47 }
48}
49
50fn extraFn(extra: u32, args: anytype) !usize {
51 if (args.len >= 1) {
52 try expect(args[0] == false);
53 }
54 if (args.len >= 2) {
55 try expect(args[1] == true);
56 }
57 return args.len;
58}
59
60const foos = [_]fn (anytype) bool{
61 foo1,
62 foo2,
63};
64
65fn foo1(args: anytype) bool {
66 return true;
67}
68fn foo2(args: anytype) bool {
69 return false;
70}
71
72test "array of var args functions" {
73 try expect(foos[0](.{}));
74 try expect(!foos[1](.{}));
75}
76
77test "pass zero length array to var args param" {
78 doNothingWithFirstArg(.{""});
79}
80
81fn doNothingWithFirstArg(args: anytype) void {
82 const a = args[0];
83}
test/stage1/behavior/vector.zig deleted-640
...@@ -1,640 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const mem = std.mem;
4const math = std.math;
5const expect = std.testing.expect;
6const expectEqual = std.testing.expectEqual;
7const expectApproxEqRel = std.testing.expectApproxEqRel;
8const Vector = std.meta.Vector;
9
10test "implicit cast vector to array - bool" {
11 const S = struct {
12 fn doTheTest() !void {
13 const a: Vector(4, bool) = [_]bool{ true, false, true, false };
14 const result_array: [4]bool = a;
15 try expect(mem.eql(bool, &result_array, &[4]bool{ true, false, true, false }));
16 }
17 };
18 try S.doTheTest();
19 comptime try S.doTheTest();
20}
21
22test "vector wrap operators" {
23 const S = struct {
24 fn doTheTest() !void {
25 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
26 var x: Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
27 try expect(mem.eql(i32, &@as([4]i32, v +% x), &[4]i32{ -2147483648, 2147483645, 33, 44 }));
28 try expect(mem.eql(i32, &@as([4]i32, v -% x), &[4]i32{ 2147483646, 2147483647, 27, 36 }));
29 try expect(mem.eql(i32, &@as([4]i32, v *% x), &[4]i32{ 2147483647, 2, 90, 160 }));
30 var z: Vector(4, i32) = [4]i32{ 1, 2, 3, -2147483648 };
31 try expect(mem.eql(i32, &@as([4]i32, -%z), &[4]i32{ -1, -2, -3, -2147483648 }));
32 }
33 };
34 try S.doTheTest();
35 comptime try S.doTheTest();
36}
37
38test "vector bin compares with mem.eql" {
39 const S = struct {
40 fn doTheTest() !void {
41 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
42 var x: Vector(4, i32) = [4]i32{ 1, 2147483647, 30, 4 };
43 try expect(mem.eql(bool, &@as([4]bool, v == x), &[4]bool{ false, false, true, false }));
44 try expect(mem.eql(bool, &@as([4]bool, v != x), &[4]bool{ true, true, false, true }));
45 try expect(mem.eql(bool, &@as([4]bool, v < x), &[4]bool{ false, true, false, false }));
46 try expect(mem.eql(bool, &@as([4]bool, v > x), &[4]bool{ true, false, false, true }));
47 try expect(mem.eql(bool, &@as([4]bool, v <= x), &[4]bool{ false, true, true, false }));
48 try expect(mem.eql(bool, &@as([4]bool, v >= x), &[4]bool{ true, false, true, true }));
49 }
50 };
51 try S.doTheTest();
52 comptime try S.doTheTest();
53}
54
55test "vector int operators" {
56 const S = struct {
57 fn doTheTest() !void {
58 var v: Vector(4, i32) = [4]i32{ 10, 20, 30, 40 };
59 var x: Vector(4, i32) = [4]i32{ 1, 2, 3, 4 };
60 try expect(mem.eql(i32, &@as([4]i32, v + x), &[4]i32{ 11, 22, 33, 44 }));
61 try expect(mem.eql(i32, &@as([4]i32, v - x), &[4]i32{ 9, 18, 27, 36 }));
62 try expect(mem.eql(i32, &@as([4]i32, v * x), &[4]i32{ 10, 40, 90, 160 }));
63 try expect(mem.eql(i32, &@as([4]i32, -v), &[4]i32{ -10, -20, -30, -40 }));
64 }
65 };
66 try S.doTheTest();
67 comptime try S.doTheTest();
68}
69
70test "vector float operators" {
71 const S = struct {
72 fn doTheTest() !void {
73 var v: Vector(4, f32) = [4]f32{ 10, 20, 30, 40 };
74 var x: Vector(4, f32) = [4]f32{ 1, 2, 3, 4 };
75 try expect(mem.eql(f32, &@as([4]f32, v + x), &[4]f32{ 11, 22, 33, 44 }));
76 try expect(mem.eql(f32, &@as([4]f32, v - x), &[4]f32{ 9, 18, 27, 36 }));
77 try expect(mem.eql(f32, &@as([4]f32, v * x), &[4]f32{ 10, 40, 90, 160 }));
78 try expect(mem.eql(f32, &@as([4]f32, -x), &[4]f32{ -1, -2, -3, -4 }));
79 }
80 };
81 try S.doTheTest();
82 comptime try S.doTheTest();
83}
84
85test "vector bit operators" {
86 const S = struct {
87 fn doTheTest() !void {
88 var v: Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 };
89 var x: Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 };
90 try expect(mem.eql(u8, &@as([4]u8, v ^ x), &[4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 }));
91 try expect(mem.eql(u8, &@as([4]u8, v | x), &[4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 }));
92 try expect(mem.eql(u8, &@as([4]u8, v & x), &[4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 }));
93 }
94 };
95 try S.doTheTest();
96 comptime try S.doTheTest();
97}
98
99test "implicit cast vector to array" {
100 const S = struct {
101 fn doTheTest() !void {
102 var a: Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };
103 var result_array: [4]i32 = a;
104 result_array = a;
105 try expect(mem.eql(i32, &result_array, &[4]i32{ 1, 2, 3, 4 }));
106 }
107 };
108 try S.doTheTest();
109 comptime try S.doTheTest();
110}
111
112test "array to vector" {
113 var foo: f32 = 3.14;
114 var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };
115 var vec: Vector(4, f32) = arr;
116}
117
118test "vector casts of sizes not divisable by 8" {
119 // https://github.com/ziglang/zig/issues/3563
120 if (std.Target.current.os.tag == .dragonfly) return error.SkipZigTest;
121
122 const S = struct {
123 fn doTheTest() !void {
124 {
125 var v: Vector(4, u3) = [4]u3{ 5, 2, 3, 0 };
126 var x: [4]u3 = v;
127 try expect(mem.eql(u3, &x, &@as([4]u3, v)));
128 }
129 {
130 var v: Vector(4, u2) = [4]u2{ 1, 2, 3, 0 };
131 var x: [4]u2 = v;
132 try expect(mem.eql(u2, &x, &@as([4]u2, v)));
133 }
134 {
135 var v: Vector(4, u1) = [4]u1{ 1, 0, 1, 0 };
136 var x: [4]u1 = v;
137 try expect(mem.eql(u1, &x, &@as([4]u1, v)));
138 }
139 {
140 var v: Vector(4, bool) = [4]bool{ false, false, true, false };
141 var x: [4]bool = v;
142 try expect(mem.eql(bool, &x, &@as([4]bool, v)));
143 }
144 }
145 };
146 try S.doTheTest();
147 comptime try S.doTheTest();
148}
149
150test "vector @splat" {
151 const S = struct {
152 fn testForT(comptime N: comptime_int, v: anytype) !void {
153 const T = @TypeOf(v);
154 var vec = @splat(N, v);
155 try expectEqual(Vector(N, T), @TypeOf(vec));
156 var as_array = @as([N]T, vec);
157 for (as_array) |elem| try expectEqual(v, elem);
158 }
159 fn doTheTest() !void {
160 // Splats with multiple-of-8 bit types that fill a 128bit vector.
161 try testForT(16, @as(u8, 0xEE));
162 try testForT(8, @as(u16, 0xBEEF));
163 try testForT(4, @as(u32, 0xDEADBEEF));
164 try testForT(2, @as(u64, 0xCAFEF00DDEADBEEF));
165
166 try testForT(8, @as(f16, 3.1415));
167 try testForT(4, @as(f32, 3.1415));
168 try testForT(2, @as(f64, 3.1415));
169
170 // Same but fill more than 128 bits.
171 try testForT(16 * 2, @as(u8, 0xEE));
172 try testForT(8 * 2, @as(u16, 0xBEEF));
173 try testForT(4 * 2, @as(u32, 0xDEADBEEF));
174 try testForT(2 * 2, @as(u64, 0xCAFEF00DDEADBEEF));
175
176 try testForT(8 * 2, @as(f16, 3.1415));
177 try testForT(4 * 2, @as(f32, 3.1415));
178 try testForT(2 * 2, @as(f64, 3.1415));
179 }
180 };
181 try S.doTheTest();
182 comptime try S.doTheTest();
183}
184
185test "load vector elements via comptime index" {
186 const S = struct {
187 fn doTheTest() !void {
188 var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
189 try expect(v[0] == 1);
190 try expect(v[1] == 2);
191 try expect(loadv(&v[2]) == 3);
192 }
193 fn loadv(ptr: anytype) i32 {
194 return ptr.*;
195 }
196 };
197
198 try S.doTheTest();
199 comptime try S.doTheTest();
200}
201
202test "store vector elements via comptime index" {
203 const S = struct {
204 fn doTheTest() !void {
205 var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
206
207 v[2] = 42;
208 try expect(v[1] == 5);
209 v[3] = -364;
210 try expect(v[2] == 42);
211 try expect(-364 == v[3]);
212
213 storev(&v[0], 100);
214 try expect(v[0] == 100);
215 }
216 fn storev(ptr: anytype, x: i32) void {
217 ptr.* = x;
218 }
219 };
220
221 try S.doTheTest();
222 comptime try S.doTheTest();
223}
224
225test "load vector elements via runtime index" {
226 const S = struct {
227 fn doTheTest() !void {
228 var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
229 var i: u32 = 0;
230 try expect(v[i] == 1);
231 i += 1;
232 try expect(v[i] == 2);
233 i += 1;
234 try expect(v[i] == 3);
235 }
236 };
237
238 try S.doTheTest();
239 comptime try S.doTheTest();
240}
241
242test "store vector elements via runtime index" {
243 const S = struct {
244 fn doTheTest() !void {
245 var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
246 var i: u32 = 2;
247 v[i] = 1;
248 try expect(v[1] == 5);
249 try expect(v[2] == 1);
250 i += 1;
251 v[i] = -364;
252 try expect(-364 == v[3]);
253 }
254 };
255
256 try S.doTheTest();
257 comptime try S.doTheTest();
258}
259
260test "initialize vector which is a struct field" {
261 const Vec4Obj = struct {
262 data: Vector(4, f32),
263 };
264
265 const S = struct {
266 fn doTheTest() !void {
267 var foo = Vec4Obj{
268 .data = [_]f32{ 1, 2, 3, 4 },
269 };
270 }
271 };
272 try S.doTheTest();
273 comptime try S.doTheTest();
274}
275
276test "vector comparison operators" {
277 const S = struct {
278 fn doTheTest() !void {
279 {
280 const v1: Vector(4, bool) = [_]bool{ true, false, true, false };
281 const v2: Vector(4, bool) = [_]bool{ false, true, false, true };
282 try expectEqual(@splat(4, true), v1 == v1);
283 try expectEqual(@splat(4, false), v1 == v2);
284 try expectEqual(@splat(4, true), v1 != v2);
285 try expectEqual(@splat(4, false), v2 != v2);
286 }
287 {
288 const v1 = @splat(4, @as(u32, 0xc0ffeeee));
289 const v2: Vector(4, c_uint) = v1;
290 const v3 = @splat(4, @as(u32, 0xdeadbeef));
291 try expectEqual(@splat(4, true), v1 == v2);
292 try expectEqual(@splat(4, false), v1 == v3);
293 try expectEqual(@splat(4, true), v1 != v3);
294 try expectEqual(@splat(4, false), v1 != v2);
295 }
296 {
297 // Comptime-known LHS/RHS
298 var v1: @Vector(4, u32) = [_]u32{ 2, 1, 2, 1 };
299 const v2 = @splat(4, @as(u32, 2));
300 const v3: @Vector(4, bool) = [_]bool{ true, false, true, false };
301 try expectEqual(v3, v1 == v2);
302 try expectEqual(v3, v2 == v1);
303 }
304 }
305 };
306 try S.doTheTest();
307 comptime try S.doTheTest();
308}
309
310test "vector division operators" {
311 const S = struct {
312 fn doTheTestDiv(comptime T: type, x: Vector(4, T), y: Vector(4, T)) !void {
313 if (!comptime std.meta.trait.isSignedInt(T)) {
314 const d0 = x / y;
315 for (@as([4]T, d0)) |v, i| {
316 try expectEqual(x[i] / y[i], v);
317 }
318 }
319 const d1 = @divExact(x, y);
320 for (@as([4]T, d1)) |v, i| {
321 try expectEqual(@divExact(x[i], y[i]), v);
322 }
323 const d2 = @divFloor(x, y);
324 for (@as([4]T, d2)) |v, i| {
325 try expectEqual(@divFloor(x[i], y[i]), v);
326 }
327 const d3 = @divTrunc(x, y);
328 for (@as([4]T, d3)) |v, i| {
329 try expectEqual(@divTrunc(x[i], y[i]), v);
330 }
331 }
332
333 fn doTheTestMod(comptime T: type, x: Vector(4, T), y: Vector(4, T)) !void {
334 if ((!comptime std.meta.trait.isSignedInt(T)) and @typeInfo(T) != .Float) {
335 const r0 = x % y;
336 for (@as([4]T, r0)) |v, i| {
337 try expectEqual(x[i] % y[i], v);
338 }
339 }
340 const r1 = @mod(x, y);
341 for (@as([4]T, r1)) |v, i| {
342 try expectEqual(@mod(x[i], y[i]), v);
343 }
344 const r2 = @rem(x, y);
345 for (@as([4]T, r2)) |v, i| {
346 try expectEqual(@rem(x[i], y[i]), v);
347 }
348 }
349
350 fn doTheTest() !void {
351 // https://github.com/ziglang/zig/issues/4952
352 if (std.builtin.os.tag != .windows) {
353 try doTheTestDiv(f16, [4]f16{ 4.0, -4.0, 4.0, -4.0 }, [4]f16{ 1.0, 2.0, -1.0, -2.0 });
354 }
355
356 try doTheTestDiv(f32, [4]f32{ 4.0, -4.0, 4.0, -4.0 }, [4]f32{ 1.0, 2.0, -1.0, -2.0 });
357 try doTheTestDiv(f64, [4]f64{ 4.0, -4.0, 4.0, -4.0 }, [4]f64{ 1.0, 2.0, -1.0, -2.0 });
358
359 // https://github.com/ziglang/zig/issues/4952
360 if (std.builtin.os.tag != .windows) {
361 try doTheTestMod(f16, [4]f16{ 4.0, -4.0, 4.0, -4.0 }, [4]f16{ 1.0, 2.0, 0.5, 3.0 });
362 }
363 try doTheTestMod(f32, [4]f32{ 4.0, -4.0, 4.0, -4.0 }, [4]f32{ 1.0, 2.0, 0.5, 3.0 });
364 try doTheTestMod(f64, [4]f64{ 4.0, -4.0, 4.0, -4.0 }, [4]f64{ 1.0, 2.0, 0.5, 3.0 });
365
366 try doTheTestDiv(i8, [4]i8{ 4, -4, 4, -4 }, [4]i8{ 1, 2, -1, -2 });
367 try doTheTestDiv(i16, [4]i16{ 4, -4, 4, -4 }, [4]i16{ 1, 2, -1, -2 });
368 try doTheTestDiv(i32, [4]i32{ 4, -4, 4, -4 }, [4]i32{ 1, 2, -1, -2 });
369 try doTheTestDiv(i64, [4]i64{ 4, -4, 4, -4 }, [4]i64{ 1, 2, -1, -2 });
370
371 try doTheTestMod(i8, [4]i8{ 4, -4, 4, -4 }, [4]i8{ 1, 2, 4, 8 });
372 try doTheTestMod(i16, [4]i16{ 4, -4, 4, -4 }, [4]i16{ 1, 2, 4, 8 });
373 try doTheTestMod(i32, [4]i32{ 4, -4, 4, -4 }, [4]i32{ 1, 2, 4, 8 });
374 try doTheTestMod(i64, [4]i64{ 4, -4, 4, -4 }, [4]i64{ 1, 2, 4, 8 });
375
376 try doTheTestDiv(u8, [4]u8{ 1, 2, 4, 8 }, [4]u8{ 1, 1, 2, 4 });
377 try doTheTestDiv(u16, [4]u16{ 1, 2, 4, 8 }, [4]u16{ 1, 1, 2, 4 });
378 try doTheTestDiv(u32, [4]u32{ 1, 2, 4, 8 }, [4]u32{ 1, 1, 2, 4 });
379 try doTheTestDiv(u64, [4]u64{ 1, 2, 4, 8 }, [4]u64{ 1, 1, 2, 4 });
380
381 try doTheTestMod(u8, [4]u8{ 1, 2, 4, 8 }, [4]u8{ 1, 1, 2, 4 });
382 try doTheTestMod(u16, [4]u16{ 1, 2, 4, 8 }, [4]u16{ 1, 1, 2, 4 });
383 try doTheTestMod(u32, [4]u32{ 1, 2, 4, 8 }, [4]u32{ 1, 1, 2, 4 });
384 try doTheTestMod(u64, [4]u64{ 1, 2, 4, 8 }, [4]u64{ 1, 1, 2, 4 });
385 }
386 };
387
388 try S.doTheTest();
389 comptime try S.doTheTest();
390}
391
392test "vector bitwise not operator" {
393 const S = struct {
394 fn doTheTestNot(comptime T: type, x: Vector(4, T)) !void {
395 var y = ~x;
396 for (@as([4]T, y)) |v, i| {
397 try expectEqual(~x[i], v);
398 }
399 }
400 fn doTheTest() !void {
401 try doTheTestNot(u8, [_]u8{ 0, 2, 4, 255 });
402 try doTheTestNot(u16, [_]u16{ 0, 2, 4, 255 });
403 try doTheTestNot(u32, [_]u32{ 0, 2, 4, 255 });
404 try doTheTestNot(u64, [_]u64{ 0, 2, 4, 255 });
405
406 try doTheTestNot(u8, [_]u8{ 0, 2, 4, 255 });
407 try doTheTestNot(u16, [_]u16{ 0, 2, 4, 255 });
408 try doTheTestNot(u32, [_]u32{ 0, 2, 4, 255 });
409 try doTheTestNot(u64, [_]u64{ 0, 2, 4, 255 });
410 }
411 };
412
413 try S.doTheTest();
414 comptime try S.doTheTest();
415}
416
417test "vector shift operators" {
418 // TODO investigate why this fails when cross-compiled to wasm.
419 if (builtin.os.tag == .wasi) return error.SkipZigTest;
420
421 const S = struct {
422 fn doTheTestShift(x: anytype, y: anytype) !void {
423 const N = @typeInfo(@TypeOf(x)).Array.len;
424 const TX = @typeInfo(@TypeOf(x)).Array.child;
425 const TY = @typeInfo(@TypeOf(y)).Array.child;
426
427 var xv = @as(Vector(N, TX), x);
428 var yv = @as(Vector(N, TY), y);
429
430 var z0 = xv >> yv;
431 for (@as([N]TX, z0)) |v, i| {
432 try expectEqual(x[i] >> y[i], v);
433 }
434 var z1 = xv << yv;
435 for (@as([N]TX, z1)) |v, i| {
436 try expectEqual(x[i] << y[i], v);
437 }
438 }
439 fn doTheTestShiftExact(x: anytype, y: anytype, dir: enum { Left, Right }) !void {
440 const N = @typeInfo(@TypeOf(x)).Array.len;
441 const TX = @typeInfo(@TypeOf(x)).Array.child;
442 const TY = @typeInfo(@TypeOf(y)).Array.child;
443
444 var xv = @as(Vector(N, TX), x);
445 var yv = @as(Vector(N, TY), y);
446
447 var z = if (dir == .Left) @shlExact(xv, yv) else @shrExact(xv, yv);
448 for (@as([N]TX, z)) |v, i| {
449 const check = if (dir == .Left) x[i] << y[i] else x[i] >> y[i];
450 try expectEqual(check, v);
451 }
452 }
453 fn doTheTest() !void {
454 try doTheTestShift([_]u8{ 0, 2, 4, math.maxInt(u8) }, [_]u3{ 2, 0, 2, 7 });
455 try doTheTestShift([_]u16{ 0, 2, 4, math.maxInt(u16) }, [_]u4{ 2, 0, 2, 15 });
456 try doTheTestShift([_]u24{ 0, 2, 4, math.maxInt(u24) }, [_]u5{ 2, 0, 2, 23 });
457 try doTheTestShift([_]u32{ 0, 2, 4, math.maxInt(u32) }, [_]u5{ 2, 0, 2, 31 });
458 try doTheTestShift([_]u64{ 0xfe, math.maxInt(u64) }, [_]u6{ 0, 63 });
459
460 try doTheTestShift([_]i8{ 0, 2, 4, math.maxInt(i8) }, [_]u3{ 2, 0, 2, 7 });
461 try doTheTestShift([_]i16{ 0, 2, 4, math.maxInt(i16) }, [_]u4{ 2, 0, 2, 7 });
462 try doTheTestShift([_]i24{ 0, 2, 4, math.maxInt(i24) }, [_]u5{ 2, 0, 2, 7 });
463 try doTheTestShift([_]i32{ 0, 2, 4, math.maxInt(i32) }, [_]u5{ 2, 0, 2, 7 });
464 try doTheTestShift([_]i64{ 0xfe, math.maxInt(i64) }, [_]u6{ 0, 63 });
465
466 try doTheTestShiftExact([_]u8{ 0, 1, 1 << 7, math.maxInt(u8) ^ 1 }, [_]u3{ 4, 0, 7, 1 }, .Right);
467 try doTheTestShiftExact([_]u16{ 0, 1, 1 << 15, math.maxInt(u16) ^ 1 }, [_]u4{ 4, 0, 15, 1 }, .Right);
468 try doTheTestShiftExact([_]u24{ 0, 1, 1 << 23, math.maxInt(u24) ^ 1 }, [_]u5{ 4, 0, 23, 1 }, .Right);
469 try doTheTestShiftExact([_]u32{ 0, 1, 1 << 31, math.maxInt(u32) ^ 1 }, [_]u5{ 4, 0, 31, 1 }, .Right);
470 try doTheTestShiftExact([_]u64{ 1 << 63, 1 }, [_]u6{ 63, 0 }, .Right);
471
472 try doTheTestShiftExact([_]u8{ 0, 1, 1, math.maxInt(u8) ^ (1 << 7) }, [_]u3{ 4, 0, 7, 1 }, .Left);
473 try doTheTestShiftExact([_]u16{ 0, 1, 1, math.maxInt(u16) ^ (1 << 15) }, [_]u4{ 4, 0, 15, 1 }, .Left);
474 try doTheTestShiftExact([_]u24{ 0, 1, 1, math.maxInt(u24) ^ (1 << 23) }, [_]u5{ 4, 0, 23, 1 }, .Left);
475 try doTheTestShiftExact([_]u32{ 0, 1, 1, math.maxInt(u32) ^ (1 << 31) }, [_]u5{ 4, 0, 31, 1 }, .Left);
476 try doTheTestShiftExact([_]u64{ 1 << 63, 1 }, [_]u6{ 0, 63 }, .Left);
477 }
478 };
479
480 switch (std.builtin.arch) {
481 .i386,
482 .aarch64,
483 .aarch64_be,
484 .aarch64_32,
485 .arm,
486 .armeb,
487 .thumb,
488 .thumbeb,
489 .mips,
490 .mipsel,
491 .mips64,
492 .mips64el,
493 .riscv64,
494 .sparcv9,
495 => {
496 // LLVM miscompiles on this architecture
497 // https://github.com/ziglang/zig/issues/4951
498 return error.SkipZigTest;
499 },
500 else => {},
501 }
502
503 try S.doTheTest();
504 comptime try S.doTheTest();
505}
506
507test "vector reduce operation" {
508 const S = struct {
509 fn doTheTestReduce(comptime op: builtin.ReduceOp, x: anytype, expected: anytype) !void {
510 const N = @typeInfo(@TypeOf(x)).Array.len;
511 const TX = @typeInfo(@TypeOf(x)).Array.child;
512
513 var r = @reduce(op, @as(Vector(N, TX), x));
514 switch (@typeInfo(TX)) {
515 .Int, .Bool => try expectEqual(expected, r),
516 .Float => {
517 const expected_nan = math.isNan(expected);
518 const got_nan = math.isNan(r);
519
520 if (expected_nan and got_nan) {
521 // Do this check explicitly as two NaN values are never
522 // equal.
523 } else {
524 try expectApproxEqRel(expected, r, math.sqrt(math.epsilon(TX)));
525 }
526 },
527 else => unreachable,
528 }
529 }
530 fn doTheTest() !void {
531 try doTheTestReduce(.Add, [4]i16{ -9, -99, -999, -9999 }, @as(i32, -11106));
532 try doTheTestReduce(.Add, [4]u16{ 9, 99, 999, 9999 }, @as(u32, 11106));
533 try doTheTestReduce(.Add, [4]i32{ -9, -99, -999, -9999 }, @as(i32, -11106));
534 try doTheTestReduce(.Add, [4]u32{ 9, 99, 999, 9999 }, @as(u32, 11106));
535 try doTheTestReduce(.Add, [4]i64{ -9, -99, -999, -9999 }, @as(i64, -11106));
536 try doTheTestReduce(.Add, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 11106));
537 try doTheTestReduce(.Add, [4]i128{ -9, -99, -999, -9999 }, @as(i128, -11106));
538 try doTheTestReduce(.Add, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 11106));
539 try doTheTestReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9));
540 try doTheTestReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9));
541 try doTheTestReduce(.Add, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 42.9));
542
543 try doTheTestReduce(.And, [4]bool{ true, false, true, true }, @as(bool, false));
544 try doTheTestReduce(.And, [4]u1{ 1, 0, 1, 1 }, @as(u1, 0));
545 try doTheTestReduce(.And, [4]u16{ 0xffff, 0xff55, 0xaaff, 0x1010 }, @as(u16, 0x10));
546 try doTheTestReduce(.And, [4]u32{ 0xffffffff, 0xffff5555, 0xaaaaffff, 0x10101010 }, @as(u32, 0x1010));
547 try doTheTestReduce(.And, [4]u64{ 0xffffffff, 0xffff5555, 0xaaaaffff, 0x10101010 }, @as(u64, 0x1010));
548
549 try doTheTestReduce(.Min, [4]i16{ -1, 2, 3, 4 }, @as(i16, -1));
550 try doTheTestReduce(.Min, [4]u16{ 1, 2, 3, 4 }, @as(u16, 1));
551 try doTheTestReduce(.Min, [4]i32{ 1234567, -386, 0, 3 }, @as(i32, -386));
552 try doTheTestReduce(.Min, [4]u32{ 99, 9999, 9, 99999 }, @as(u32, 9));
553
554 // LLVM 11 ERROR: Cannot select type
555 // https://github.com/ziglang/zig/issues/7138
556 if (std.builtin.arch != .aarch64) {
557 try doTheTestReduce(.Min, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, -386));
558 try doTheTestReduce(.Min, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 9));
559 }
560
561 try doTheTestReduce(.Min, [4]i128{ 1234567, -386, 0, 3 }, @as(i128, -386));
562 try doTheTestReduce(.Min, [4]u128{ 99, 9999, 9, 99999 }, @as(u128, 9));
563 try doTheTestReduce(.Min, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, -100.0));
564 try doTheTestReduce(.Min, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, -100.0));
565 try doTheTestReduce(.Min, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, -100.0));
566
567 try doTheTestReduce(.Max, [4]i16{ -1, 2, 3, 4 }, @as(i16, 4));
568 try doTheTestReduce(.Max, [4]u16{ 1, 2, 3, 4 }, @as(u16, 4));
569 try doTheTestReduce(.Max, [4]i32{ 1234567, -386, 0, 3 }, @as(i32, 1234567));
570 try doTheTestReduce(.Max, [4]u32{ 99, 9999, 9, 99999 }, @as(u32, 99999));
571
572 // LLVM 11 ERROR: Cannot select type
573 // https://github.com/ziglang/zig/issues/7138
574 if (std.builtin.arch != .aarch64) {
575 try doTheTestReduce(.Max, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, 1234567));
576 try doTheTestReduce(.Max, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 99999));
577 }
578
579 try doTheTestReduce(.Max, [4]i128{ 1234567, -386, 0, 3 }, @as(i128, 1234567));
580 try doTheTestReduce(.Max, [4]u128{ 99, 9999, 9, 99999 }, @as(u128, 99999));
581 try doTheTestReduce(.Max, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, 10.0e9));
582 try doTheTestReduce(.Max, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, 10.0e9));
583 try doTheTestReduce(.Max, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, 10.0e9));
584
585 try doTheTestReduce(.Mul, [4]i16{ -1, 2, 3, 4 }, @as(i16, -24));
586 try doTheTestReduce(.Mul, [4]u16{ 1, 2, 3, 4 }, @as(u16, 24));
587 try doTheTestReduce(.Mul, [4]i32{ -9, -99, -999, 999 }, @as(i32, -889218891));
588 try doTheTestReduce(.Mul, [4]u32{ 1, 2, 3, 4 }, @as(u32, 24));
589 try doTheTestReduce(.Mul, [4]i64{ 9, 99, 999, 9999 }, @as(i64, 8900199891));
590 try doTheTestReduce(.Mul, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 8900199891));
591 try doTheTestReduce(.Mul, [4]i128{ -9, -99, -999, 9999 }, @as(i128, -8900199891));
592 try doTheTestReduce(.Mul, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 8900199891));
593 try doTheTestReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7));
594 try doTheTestReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7));
595 try doTheTestReduce(.Mul, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 58430.7));
596
597 try doTheTestReduce(.Or, [4]bool{ false, true, false, false }, @as(bool, true));
598 try doTheTestReduce(.Or, [4]u1{ 0, 1, 0, 0 }, @as(u1, 1));
599 try doTheTestReduce(.Or, [4]u16{ 0xff00, 0xff00, 0xf0, 0xf }, ~@as(u16, 0));
600 try doTheTestReduce(.Or, [4]u32{ 0xffff0000, 0xff00, 0xf0, 0xf }, ~@as(u32, 0));
601 try doTheTestReduce(.Or, [4]u64{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u64, 0xffffffff));
602 try doTheTestReduce(.Or, [4]u128{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u128, 0xffffffff));
603
604 try doTheTestReduce(.Xor, [4]bool{ true, true, true, false }, @as(bool, true));
605 try doTheTestReduce(.Xor, [4]u1{ 1, 1, 1, 0 }, @as(u1, 1));
606 try doTheTestReduce(.Xor, [4]u16{ 0x0000, 0x3333, 0x8888, 0x4444 }, ~@as(u16, 0));
607 try doTheTestReduce(.Xor, [4]u32{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, ~@as(u32, 0));
608 try doTheTestReduce(.Xor, [4]u64{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, @as(u64, 0xffffffff));
609 try doTheTestReduce(.Xor, [4]u128{ 0x00000000, 0x33333333, 0x88888888, 0x44444444 }, @as(u128, 0xffffffff));
610
611 // Test the reduction on vectors containing NaNs.
612 const f16_nan = math.nan(f16);
613 const f32_nan = math.nan(f32);
614 const f64_nan = math.nan(f64);
615
616 try doTheTestReduce(.Add, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
617 try doTheTestReduce(.Add, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
618 try doTheTestReduce(.Add, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
619
620 // LLVM 11 ERROR: Cannot select type
621 // https://github.com/ziglang/zig/issues/7138
622 if (false) {
623 try doTheTestReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
624 try doTheTestReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
625 try doTheTestReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
626
627 try doTheTestReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
628 try doTheTestReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
629 try doTheTestReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
630 }
631
632 try doTheTestReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
633 try doTheTestReduce(.Mul, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
634 try doTheTestReduce(.Mul, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
635 }
636 };
637
638 try S.doTheTest();
639 comptime try S.doTheTest();
640}
test/stage1/behavior/void.zig deleted-40
...@@ -1,40 +0,0 @@
1const expect = @import("std").testing.expect;
2
3const Foo = struct {
4 a: void,
5 b: i32,
6 c: void,
7};
8
9test "compare void with void compile time known" {
10 comptime {
11 const foo = Foo{
12 .a = {},
13 .b = 1,
14 .c = {},
15 };
16 try expect(foo.a == {});
17 }
18}
19
20test "iterate over a void slice" {
21 var j: usize = 0;
22 for (times(10)) |_, i| {
23 try expect(i == j);
24 j += 1;
25 }
26}
27
28fn times(n: usize) []const void {
29 return @as([*]void, undefined)[0..n];
30}
31
32test "void optional" {
33 var x: ?void = {};
34 try expect(x != null);
35}
36
37test "void array as a local variable initializer" {
38 var x = [_]void{{}} ** 1004;
39 var y = x[0];
40}
test/stage1/behavior/wasm.zig deleted-8
...@@ -1,8 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "memory size and grow" {
5 var prev = @wasmMemorySize(0);
6 try expect(prev == @wasmMemoryGrow(0, 1));
7 try expect(prev + 1 == @wasmMemorySize(0));
8}
test/stage1/behavior/while.zig deleted-283
...@@ -1,283 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "while loop" {
5 var i: i32 = 0;
6 while (i < 4) {
7 i += 1;
8 }
9 try expect(i == 4);
10 try expect(whileLoop1() == 1);
11}
12fn whileLoop1() i32 {
13 return whileLoop2();
14}
15fn whileLoop2() i32 {
16 while (true) {
17 return 1;
18 }
19}
20
21test "static eval while" {
22 try expect(static_eval_while_number == 1);
23}
24const static_eval_while_number = staticWhileLoop1();
25fn staticWhileLoop1() i32 {
26 return whileLoop2();
27}
28fn staticWhileLoop2() i32 {
29 while (true) {
30 return 1;
31 }
32}
33
34test "continue and break" {
35 try runContinueAndBreakTest();
36 try expect(continue_and_break_counter == 8);
37}
38var continue_and_break_counter: i32 = 0;
39fn runContinueAndBreakTest() !void {
40 var i: i32 = 0;
41 while (true) {
42 continue_and_break_counter += 2;
43 i += 1;
44 if (i < 4) {
45 continue;
46 }
47 break;
48 }
49 try expect(i == 4);
50}
51
52test "return with implicit cast from while loop" {
53 returnWithImplicitCastFromWhileLoopTest() catch unreachable;
54}
55fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
56 while (true) {
57 return;
58 }
59}
60
61test "while with continue expression" {
62 var sum: i32 = 0;
63 {
64 var i: i32 = 0;
65 while (i < 10) : (i += 1) {
66 if (i == 5) continue;
67 sum += i;
68 }
69 }
70 try expect(sum == 40);
71}
72
73test "while with else" {
74 var sum: i32 = 0;
75 var i: i32 = 0;
76 var got_else: i32 = 0;
77 while (i < 10) : (i += 1) {
78 sum += 1;
79 } else {
80 got_else += 1;
81 }
82 try expect(sum == 10);
83 try expect(got_else == 1);
84}
85
86test "while with optional as condition" {
87 numbers_left = 10;
88 var sum: i32 = 0;
89 while (getNumberOrNull()) |value| {
90 sum += value;
91 }
92 try expect(sum == 45);
93}
94
95test "while with optional as condition with else" {
96 numbers_left = 10;
97 var sum: i32 = 0;
98 var got_else: i32 = 0;
99 while (getNumberOrNull()) |value| {
100 sum += value;
101 try expect(got_else == 0);
102 } else {
103 got_else += 1;
104 }
105 try expect(sum == 45);
106 try expect(got_else == 1);
107}
108
109test "while with error union condition" {
110 numbers_left = 10;
111 var sum: i32 = 0;
112 var got_else: i32 = 0;
113 while (getNumberOrErr()) |value| {
114 sum += value;
115 } else |err| {
116 try expect(err == error.OutOfNumbers);
117 got_else += 1;
118 }
119 try expect(sum == 45);
120 try expect(got_else == 1);
121}
122
123var numbers_left: i32 = undefined;
124fn getNumberOrErr() anyerror!i32 {
125 return if (numbers_left == 0) error.OutOfNumbers else x: {
126 numbers_left -= 1;
127 break :x numbers_left;
128 };
129}
130fn getNumberOrNull() ?i32 {
131 return if (numbers_left == 0) null else x: {
132 numbers_left -= 1;
133 break :x numbers_left;
134 };
135}
136
137test "while on optional with else result follow else prong" {
138 const result = while (returnNull()) |value| {
139 break value;
140 } else @as(i32, 2);
141 try expect(result == 2);
142}
143
144test "while on optional with else result follow break prong" {
145 const result = while (returnOptional(10)) |value| {
146 break value;
147 } else @as(i32, 2);
148 try expect(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| @as(i32, 2);
155 try expect(result == 2);
156}
157
158test "while on error union with else result follow break prong" {
159 const result = while (returnSuccess(10)) |value| {
160 break value;
161 } else |err| @as(i32, 2);
162 try expect(result == 10);
163}
164
165test "while on bool with else result follow else prong" {
166 const result = while (returnFalse()) {
167 break @as(i32, 10);
168 } else @as(i32, 2);
169 try expect(result == 2);
170}
171
172test "while on bool with else result follow break prong" {
173 const result = while (returnTrue()) {
174 break @as(i32, 10);
175 } else @as(i32, 2);
176 try expect(result == 10);
177}
178
179test "break from outer while loop" {
180 testBreakOuter();
181 comptime testBreakOuter();
182}
183
184fn testBreakOuter() void {
185 outer: while (true) {
186 while (true) {
187 break :outer;
188 }
189 }
190}
191
192test "continue outer while loop" {
193 testContinueOuter();
194 comptime testContinueOuter();
195}
196
197fn testContinueOuter() void {
198 var i: usize = 0;
199 outer: while (i < 10) : (i += 1) {
200 while (true) {
201 continue :outer;
202 }
203 }
204}
205
206fn returnNull() ?i32 {
207 return null;
208}
209fn returnOptional(x: i32) ?i32 {
210 return x;
211}
212fn returnError() anyerror!i32 {
213 return error.YouWantedAnError;
214}
215fn returnSuccess(x: i32) anyerror!i32 {
216 return x;
217}
218fn returnFalse() bool {
219 return false;
220}
221fn returnTrue() bool {
222 return true;
223}
224
225test "while bool 2 break statements and an else" {
226 const S = struct {
227 fn entry(t: bool, f: bool) !void {
228 var ok = false;
229 ok = while (t) {
230 if (f) break false;
231 if (t) break true;
232 } else false;
233 try expect(ok);
234 }
235 };
236 try S.entry(true, false);
237 comptime try S.entry(true, false);
238}
239
240test "while optional 2 break statements and an else" {
241 const S = struct {
242 fn entry(opt_t: ?bool, f: bool) !void {
243 var ok = false;
244 ok = while (opt_t) |t| {
245 if (f) break false;
246 if (t) break true;
247 } else false;
248 try expect(ok);
249 }
250 };
251 try S.entry(true, false);
252 comptime try S.entry(true, false);
253}
254
255test "while error 2 break statements and an else" {
256 const S = struct {
257 fn entry(opt_t: anyerror!bool, f: bool) !void {
258 var ok = false;
259 ok = while (opt_t) |t| {
260 if (f) break false;
261 if (t) break true;
262 } else |_| false;
263 try expect(ok);
264 }
265 };
266 try S.entry(true, false);
267 comptime try S.entry(true, false);
268}
269
270test "while copies its payload" {
271 const S = struct {
272 fn doTheTest() !void {
273 var tmp: ?i32 = 10;
274 while (tmp) |value| {
275 // Modify the original variable
276 tmp = null;
277 try expect(value == 10);
278 }
279 }
280 };
281 try S.doTheTest();
282 comptime try S.doTheTest();
283}
test/stage1/behavior/widening.zig deleted-39
...@@ -1,39 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4
5test "integer widening" {
6 var a: u8 = 250;
7 var b: u16 = a;
8 var c: u32 = b;
9 var d: u64 = c;
10 var e: u64 = d;
11 var f: u128 = e;
12 try expect(f == a);
13}
14
15test "implicit unsigned integer to signed integer" {
16 var a: u8 = 250;
17 var b: i16 = a;
18 try expect(b == 250);
19}
20
21test "float widening" {
22 var a: f16 = 12.34;
23 var b: f32 = a;
24 var c: f64 = b;
25 var d: f128 = c;
26 try expect(a == b);
27 try expect(b == c);
28 try expect(c == d);
29}
30
31test "float widening f16 to f128" {
32 // TODO https://github.com/ziglang/zig/issues/3282
33 if (@import("builtin").arch == .aarch64) return error.SkipZigTest;
34 if (@import("builtin").arch == .powerpc64le) return error.SkipZigTest;
35
36 var x: f16 = 12.34;
37 var y: f128 = x;
38 try expect(x == y);
39}
test/stage2/aarch64.zig+2-2
...@@ -11,7 +11,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -11,7 +11,7 @@ pub fn addCases(ctx: *TestContext) !void {
11 var case = ctx.exe("linux_aarch64 hello world", linux_aarch64);11 var case = ctx.exe("linux_aarch64 hello world", linux_aarch64);
12 // Regular old hello world12 // Regular old hello world
13 case.addCompareOutput(13 case.addCompareOutput(
14 \\export fn _start() noreturn {14 \\pub export fn _start() noreturn {
15 \\ print();15 \\ print();
16 \\ exit();16 \\ exit();
17 \\}17 \\}
...@@ -51,7 +51,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -51,7 +51,7 @@ pub fn addCases(ctx: *TestContext) !void {
51 var case = ctx.exe("exit fn taking argument", linux_aarch64);51 var case = ctx.exe("exit fn taking argument", linux_aarch64);
5252
53 case.addCompareOutput(53 case.addCompareOutput(
54 \\export fn _start() noreturn {54 \\pub export fn _start() noreturn {
55 \\ exit(0);55 \\ exit(0);
56 \\}56 \\}
57 \\57 \\
test/stage2/arm.zig+19-172
...@@ -9,9 +9,9 @@ const linux_arm = std.zig.CrossTarget{...@@ -9,9 +9,9 @@ const linux_arm = std.zig.CrossTarget{
9pub fn addCases(ctx: *TestContext) !void {9pub fn addCases(ctx: *TestContext) !void {
10 {10 {
11 var case = ctx.exe("linux_arm hello world", linux_arm);11 var case = ctx.exe("linux_arm hello world", linux_arm);
12 // Regular old hello world12 // Hello world using _start and inline asm.
13 case.addCompareOutput(13 case.addCompareOutput(
14 \\export fn _start() noreturn {14 \\pub export fn _start() noreturn {
15 \\ print();15 \\ print();
16 \\ exit();16 \\ exit();
17 \\}17 \\}
...@@ -50,9 +50,8 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -50,9 +50,8 @@ pub fn addCases(ctx: *TestContext) !void {
50 // be in a specific order because otherwise the write to r050 // be in a specific order because otherwise the write to r0
51 // would overwrite the len parameter which resides in r051 // would overwrite the len parameter which resides in r0
52 case.addCompareOutput(52 case.addCompareOutput(
53 \\export fn _start() noreturn {53 \\pub fn main() void {
54 \\ print(id(14));54 \\ print(id(14));
55 \\ exit();
56 \\}55 \\}
57 \\56 \\
58 \\fn id(x: u32) u32 {57 \\fn id(x: u32) u32 {
...@@ -70,16 +69,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -70,16 +69,6 @@ pub fn addCases(ctx: *TestContext) !void {
70 \\ );69 \\ );
71 \\ return;70 \\ return;
72 \\}71 \\}
73 \\
74 \\fn exit() noreturn {
75 \\ asm volatile ("svc #0"
76 \\ :
77 \\ : [number] "{r7}" (1),
78 \\ [arg1] "{r0}" (0)
79 \\ : "memory"
80 \\ );
81 \\ unreachable;
82 \\}
83 ,72 ,
84 "Hello, World!\n",73 "Hello, World!\n",
85 );74 );
...@@ -89,9 +78,8 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -89,9 +78,8 @@ pub fn addCases(ctx: *TestContext) !void {
89 var case = ctx.exe("non-leaf functions", linux_arm);78 var case = ctx.exe("non-leaf functions", linux_arm);
90 // Testing non-leaf functions79 // Testing non-leaf functions
91 case.addCompareOutput(80 case.addCompareOutput(
92 \\export fn _start() noreturn {81 \\pub fn main() void {
93 \\ foo();82 \\ foo();
94 \\ exit();
95 \\}83 \\}
96 \\84 \\
97 \\fn foo() void {85 \\fn foo() void {
...@@ -99,16 +87,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -99,16 +87,6 @@ pub fn addCases(ctx: *TestContext) !void {
99 \\}87 \\}
100 \\88 \\
101 \\fn bar() void {}89 \\fn bar() void {}
102 \\
103 \\fn exit() noreturn {
104 \\ asm volatile ("svc #0"
105 \\ :
106 \\ : [number] "{r7}" (1),
107 \\ [arg1] "{r0}" (0)
108 \\ : "memory"
109 \\ );
110 \\ unreachable;
111 \\}
112 ,90 ,
113 "",91 "",
114 );92 );
...@@ -119,10 +97,9 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -119,10 +97,9 @@ pub fn addCases(ctx: *TestContext) !void {
11997
120 // Add two numbers98 // Add two numbers
121 case.addCompareOutput(99 case.addCompareOutput(
122 \\export fn _start() noreturn {100 \\pub fn main() void {
123 \\ print(2, 4);101 \\ print(2, 4);
124 \\ print(1, 7);102 \\ print(1, 7);
125 \\ exit();
126 \\}103 \\}
127 \\104 \\
128 \\fn print(a: u32, b: u32) void {105 \\fn print(a: u32, b: u32) void {
...@@ -136,26 +113,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -136,26 +113,15 @@ pub fn addCases(ctx: *TestContext) !void {
136 \\ );113 \\ );
137 \\ return;114 \\ return;
138 \\}115 \\}
139 \\
140 \\fn exit() noreturn {
141 \\ asm volatile ("svc #0"
142 \\ :
143 \\ : [number] "{r7}" (1),
144 \\ [arg1] "{r0}" (0)
145 \\ : "memory"
146 \\ );
147 \\ unreachable;
148 \\}
149 ,116 ,
150 "12345612345678",117 "12345612345678",
151 );118 );
152119
153 // Subtract two numbers120 // Subtract two numbers
154 case.addCompareOutput(121 case.addCompareOutput(
155 \\export fn _start() noreturn {122 \\pub fn main() void {
156 \\ print(10, 5);123 \\ print(10, 5);
157 \\ print(4, 3);124 \\ print(4, 3);
158 \\ exit();
159 \\}125 \\}
160 \\126 \\
161 \\fn print(a: u32, b: u32) void {127 \\fn print(a: u32, b: u32) void {
...@@ -169,26 +135,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -169,26 +135,15 @@ pub fn addCases(ctx: *TestContext) !void {
169 \\ );135 \\ );
170 \\ return;136 \\ return;
171 \\}137 \\}
172 \\
173 \\fn exit() noreturn {
174 \\ asm volatile ("svc #0"
175 \\ :
176 \\ : [number] "{r7}" (1),
177 \\ [arg1] "{r0}" (0)
178 \\ : "memory"
179 \\ );
180 \\ unreachable;
181 \\}
182 ,138 ,
183 "123451",139 "123451",
184 );140 );
185141
186 // Bitwise And142 // Bitwise And
187 case.addCompareOutput(143 case.addCompareOutput(
188 \\export fn _start() noreturn {144 \\pub fn main() void {
189 \\ print(8, 9);145 \\ print(8, 9);
190 \\ print(3, 7);146 \\ print(3, 7);
191 \\ exit();
192 \\}147 \\}
193 \\148 \\
194 \\fn print(a: u32, b: u32) void {149 \\fn print(a: u32, b: u32) void {
...@@ -202,26 +157,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -202,26 +157,15 @@ pub fn addCases(ctx: *TestContext) !void {
202 \\ );157 \\ );
203 \\ return;158 \\ return;
204 \\}159 \\}
205 \\
206 \\fn exit() noreturn {
207 \\ asm volatile ("svc #0"
208 \\ :
209 \\ : [number] "{r7}" (1),
210 \\ [arg1] "{r0}" (0)
211 \\ : "memory"
212 \\ );
213 \\ unreachable;
214 \\}
215 ,160 ,
216 "12345678123",161 "12345678123",
217 );162 );
218163
219 // Bitwise Or164 // Bitwise Or
220 case.addCompareOutput(165 case.addCompareOutput(
221 \\export fn _start() noreturn {166 \\pub fn main() void {
222 \\ print(4, 2);167 \\ print(4, 2);
223 \\ print(3, 7);168 \\ print(3, 7);
224 \\ exit();
225 \\}169 \\}
226 \\170 \\
227 \\fn print(a: u32, b: u32) void {171 \\fn print(a: u32, b: u32) void {
...@@ -235,26 +179,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -235,26 +179,15 @@ pub fn addCases(ctx: *TestContext) !void {
235 \\ );179 \\ );
236 \\ return;180 \\ return;
237 \\}181 \\}
238 \\
239 \\fn exit() noreturn {
240 \\ asm volatile ("svc #0"
241 \\ :
242 \\ : [number] "{r7}" (1),
243 \\ [arg1] "{r0}" (0)
244 \\ : "memory"
245 \\ );
246 \\ unreachable;
247 \\}
248 ,182 ,
249 "1234561234567",183 "1234561234567",
250 );184 );
251185
252 // Bitwise Xor186 // Bitwise Xor
253 case.addCompareOutput(187 case.addCompareOutput(
254 \\export fn _start() noreturn {188 \\pub fn main() void {
255 \\ print(42, 42);189 \\ print(42, 42);
256 \\ print(3, 5);190 \\ print(3, 5);
257 \\ exit();
258 \\}191 \\}
259 \\192 \\
260 \\fn print(a: u32, b: u32) void {193 \\fn print(a: u32, b: u32) void {
...@@ -268,16 +201,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -268,16 +201,6 @@ pub fn addCases(ctx: *TestContext) !void {
268 \\ );201 \\ );
269 \\ return;202 \\ return;
270 \\}203 \\}
271 \\
272 \\fn exit() noreturn {
273 \\ asm volatile ("svc #0"
274 \\ :
275 \\ : [number] "{r7}" (1),
276 \\ [arg1] "{r0}" (0)
277 \\ : "memory"
278 \\ );
279 \\ unreachable;
280 \\}
281 ,204 ,
282 "123456",205 "123456",
283 );206 );
...@@ -287,26 +210,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -287,26 +210,15 @@ pub fn addCases(ctx: *TestContext) !void {
287 var case = ctx.exe("if statements", linux_arm);210 var case = ctx.exe("if statements", linux_arm);
288 // Simple if statement in assert211 // Simple if statement in assert
289 case.addCompareOutput(212 case.addCompareOutput(
290 \\export fn _start() noreturn {213 \\pub fn main() void {
291 \\ var x: u32 = 123;214 \\ var x: u32 = 123;
292 \\ var y: u32 = 42;215 \\ var y: u32 = 42;
293 \\ assert(x > y);216 \\ assert(x > y);
294 \\ exit();
295 \\}217 \\}
296 \\218 \\
297 \\fn assert(ok: bool) void {219 \\fn assert(ok: bool) void {
298 \\ if (!ok) unreachable;220 \\ if (!ok) unreachable;
299 \\}221 \\}
300 \\
301 \\fn exit() noreturn {
302 \\ asm volatile ("svc #0"
303 \\ :
304 \\ : [number] "{r7}" (1),
305 \\ [arg1] "{r0}" (0)
306 \\ : "memory"
307 \\ );
308 \\ unreachable;
309 \\}
310 ,222 ,
311 "",223 "",
312 );224 );
...@@ -316,7 +228,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -316,7 +228,7 @@ pub fn addCases(ctx: *TestContext) !void {
316 var case = ctx.exe("while loops", linux_arm);228 var case = ctx.exe("while loops", linux_arm);
317 // Simple while loop with assert229 // Simple while loop with assert
318 case.addCompareOutput(230 case.addCompareOutput(
319 \\export fn _start() noreturn {231 \\pub fn main() void {
320 \\ var x: u32 = 2020;232 \\ var x: u32 = 2020;
321 \\ var i: u32 = 0;233 \\ var i: u32 = 0;
322 \\ while (x > 0) {234 \\ while (x > 0) {
...@@ -324,22 +236,11 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -324,22 +236,11 @@ pub fn addCases(ctx: *TestContext) !void {
324 \\ i += 1;236 \\ i += 1;
325 \\ }237 \\ }
326 \\ assert(i == 1010);238 \\ assert(i == 1010);
327 \\ exit();
328 \\}239 \\}
329 \\240 \\
330 \\fn assert(ok: bool) void {241 \\fn assert(ok: bool) void {
331 \\ if (!ok) unreachable;242 \\ if (!ok) unreachable;
332 \\}243 \\}
333 \\
334 \\fn exit() noreturn {
335 \\ asm volatile ("svc #0"
336 \\ :
337 \\ : [number] "{r7}" (1),
338 \\ [arg1] "{r0}" (0)
339 \\ : "memory"
340 \\ );
341 \\ unreachable;
342 \\}
343 ,244 ,
344 "",245 "",
345 );246 );
...@@ -349,12 +250,11 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -349,12 +250,11 @@ pub fn addCases(ctx: *TestContext) !void {
349 var case = ctx.exe("integer multiplication", linux_arm);250 var case = ctx.exe("integer multiplication", linux_arm);
350 // Simple u32 integer multiplication251 // Simple u32 integer multiplication
351 case.addCompareOutput(252 case.addCompareOutput(
352 \\export fn _start() noreturn {253 \\pub fn main() void {
353 \\ assert(mul(1, 1) == 1);254 \\ assert(mul(1, 1) == 1);
354 \\ assert(mul(42, 1) == 42);255 \\ assert(mul(42, 1) == 42);
355 \\ assert(mul(1, 42) == 42);256 \\ assert(mul(1, 42) == 42);
356 \\ assert(mul(123, 42) == 5166);257 \\ assert(mul(123, 42) == 5166);
357 \\ exit();
358 \\}258 \\}
359 \\259 \\
360 \\fn mul(x: u32, y: u32) u32 {260 \\fn mul(x: u32, y: u32) u32 {
...@@ -364,16 +264,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -364,16 +264,6 @@ pub fn addCases(ctx: *TestContext) !void {
364 \\fn assert(ok: bool) void {264 \\fn assert(ok: bool) void {
365 \\ if (!ok) unreachable;265 \\ if (!ok) unreachable;
366 \\}266 \\}
367 \\
368 \\fn exit() noreturn {
369 \\ asm volatile ("svc #0"
370 \\ :
371 \\ : [number] "{r7}" (1),
372 \\ [arg1] "{r0}" (0)
373 \\ : "memory"
374 \\ );
375 \\ unreachable;
376 \\}
377 ,267 ,
378 "",268 "",
379 );269 );
...@@ -385,9 +275,8 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -385,9 +275,8 @@ pub fn addCases(ctx: *TestContext) !void {
385 // callee preserved register, otherwise it will be overwritten275 // callee preserved register, otherwise it will be overwritten
386 // by the first parameter to baz.276 // by the first parameter to baz.
387 case.addCompareOutput(277 case.addCompareOutput(
388 \\export fn _start() noreturn {278 \\pub fn main() void {
389 \\ assert(foo() == 43);279 \\ assert(foo() == 43);
390 \\ exit();
391 \\}280 \\}
392 \\281 \\
393 \\fn foo() u32 {282 \\fn foo() u32 {
...@@ -405,16 +294,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -405,16 +294,6 @@ pub fn addCases(ctx: *TestContext) !void {
405 \\fn assert(ok: bool) void {294 \\fn assert(ok: bool) void {
406 \\ if (!ok) unreachable;295 \\ if (!ok) unreachable;
407 \\}296 \\}
408 \\
409 \\fn exit() noreturn {
410 \\ asm volatile ("svc #0"
411 \\ :
412 \\ : [number] "{r7}" (1),
413 \\ [arg1] "{r0}" (0)
414 \\ : "memory"
415 \\ );
416 \\ unreachable;
417 \\}
418 ,297 ,
419 "",298 "",
420 );299 );
...@@ -423,14 +302,13 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -423,14 +302,13 @@ pub fn addCases(ctx: *TestContext) !void {
423 {302 {
424 var case = ctx.exe("recursive fibonacci", linux_arm);303 var case = ctx.exe("recursive fibonacci", linux_arm);
425 case.addCompareOutput(304 case.addCompareOutput(
426 \\export fn _start() noreturn {305 \\pub fn main() void {
427 \\ assert(fib(0) == 0);306 \\ assert(fib(0) == 0);
428 \\ assert(fib(1) == 1);307 \\ assert(fib(1) == 1);
429 \\ assert(fib(2) == 1);308 \\ assert(fib(2) == 1);
430 \\ assert(fib(3) == 2);309 \\ assert(fib(3) == 2);
431 \\ assert(fib(10) == 55);310 \\ assert(fib(10) == 55);
432 \\ assert(fib(20) == 6765);311 \\ assert(fib(20) == 6765);
433 \\ exit();
434 \\}312 \\}
435 \\313 \\
436 \\fn fib(n: u32) u32 {314 \\fn fib(n: u32) u32 {
...@@ -444,16 +322,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -444,16 +322,6 @@ pub fn addCases(ctx: *TestContext) !void {
444 \\fn assert(ok: bool) void {322 \\fn assert(ok: bool) void {
445 \\ if (!ok) unreachable;323 \\ if (!ok) unreachable;
446 \\}324 \\}
447 \\
448 \\fn exit() noreturn {
449 \\ asm volatile ("svc #0"
450 \\ :
451 \\ : [number] "{r7}" (1),
452 \\ [arg1] "{r0}" (0)
453 \\ : "memory"
454 \\ );
455 \\ unreachable;
456 \\}
457 ,325 ,
458 "",326 "",
459 );327 );
...@@ -462,9 +330,8 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -462,9 +330,8 @@ pub fn addCases(ctx: *TestContext) !void {
462 {330 {
463 var case = ctx.exe("spilling registers", linux_arm);331 var case = ctx.exe("spilling registers", linux_arm);
464 case.addCompareOutput(332 case.addCompareOutput(
465 \\export fn _start() noreturn {333 \\pub fn main() void {
466 \\ assert(add(3, 4) == 791);334 \\ assert(add(3, 4) == 791);
467 \\ exit();
468 \\}335 \\}
469 \\336 \\
470 \\fn add(a: u32, b: u32) u32 {337 \\fn add(a: u32, b: u32) u32 {
...@@ -497,24 +364,13 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -497,24 +364,13 @@ pub fn addCases(ctx: *TestContext) !void {
497 \\fn assert(ok: bool) void {364 \\fn assert(ok: bool) void {
498 \\ if (!ok) unreachable;365 \\ if (!ok) unreachable;
499 \\}366 \\}
500 \\
501 \\fn exit() noreturn {
502 \\ asm volatile ("svc #0"
503 \\ :
504 \\ : [number] "{r7}" (1),
505 \\ [arg1] "{r0}" (0)
506 \\ : "memory"
507 \\ );
508 \\ unreachable;
509 \\}
510 ,367 ,
511 "",368 "",
512 );369 );
513370
514 case.addCompareOutput(371 case.addCompareOutput(
515 \\export fn _start() noreturn {372 \\pub fn main() void {
516 \\ assert(addMul(3, 4) == 357747496);373 \\ assert(addMul(3, 4) == 357747496);
517 \\ exit();
518 \\}374 \\}
519 \\375 \\
520 \\fn addMul(a: u32, b: u32) u32 {376 \\fn addMul(a: u32, b: u32) u32 {
...@@ -547,17 +403,8 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -547,17 +403,8 @@ pub fn addCases(ctx: *TestContext) !void {
547 \\fn assert(ok: bool) void {403 \\fn assert(ok: bool) void {
548 \\ if (!ok) unreachable;404 \\ if (!ok) unreachable;
549 \\}405 \\}
550 \\406 ,
551 \\fn exit() noreturn {407 "",
552 \\ asm volatile ("svc #0"408 );
553 \\ :
554 \\ : [number] "{r7}" (1),
555 \\ [arg1] "{r0}" (0)
556 \\ : "memory"
557 \\ );
558 \\ unreachable;
559 \\}
560 ,
561 "",);
562 }409 }
563}410}
test/stage2/cbe.zig+59-55
...@@ -15,7 +15,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -15,7 +15,7 @@ pub fn addCases(ctx: *TestContext) !void {
15 // Regular old hello world15 // Regular old hello world
16 case.addCompareOutput(16 case.addCompareOutput(
17 \\extern fn puts(s: [*:0]const u8) c_int;17 \\extern fn puts(s: [*:0]const u8) c_int;
18 \\export fn main() c_int {18 \\pub export fn main() c_int {
19 \\ _ = puts("hello world!");19 \\ _ = puts("hello world!");
20 \\ return 0;20 \\ return 0;
21 \\}21 \\}
...@@ -24,7 +24,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -24,7 +24,7 @@ pub fn addCases(ctx: *TestContext) !void {
24 // Now change the message only24 // Now change the message only
25 case.addCompareOutput(25 case.addCompareOutput(
26 \\extern fn puts(s: [*:0]const u8) c_int;26 \\extern fn puts(s: [*:0]const u8) c_int;
27 \\export fn main() c_int {27 \\pub export fn main() c_int {
28 \\ _ = puts("yo");28 \\ _ = puts("yo");
29 \\ return 0;29 \\ return 0;
30 \\}30 \\}
...@@ -33,7 +33,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -33,7 +33,7 @@ pub fn addCases(ctx: *TestContext) !void {
33 // Add an unused Decl33 // Add an unused Decl
34 case.addCompareOutput(34 case.addCompareOutput(
35 \\extern fn puts(s: [*:0]const u8) c_int;35 \\extern fn puts(s: [*:0]const u8) c_int;
36 \\export fn main() c_int {36 \\pub export fn main() c_int {
37 \\ _ = puts("yo!");37 \\ _ = puts("yo!");
38 \\ return 0;38 \\ return 0;
39 \\}39 \\}
...@@ -43,7 +43,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -43,7 +43,7 @@ pub fn addCases(ctx: *TestContext) !void {
43 // Comptime return type and calling convention expected.43 // Comptime return type and calling convention expected.
44 case.addError(44 case.addError(
45 \\var x: i32 = 1234;45 \\var x: i32 = 1234;
46 \\export fn main() x {46 \\pub export fn main() x {
47 \\ return 0;47 \\ return 0;
48 \\}48 \\}
49 \\export fn foo() callconv(y) c_int {49 \\export fn foo() callconv(y) c_int {
...@@ -51,7 +51,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -51,7 +51,7 @@ pub fn addCases(ctx: *TestContext) !void {
51 \\}51 \\}
52 \\var y: i32 = 1234;52 \\var y: i32 = 1234;
53 , &.{53 , &.{
54 ":2:18: error: unable to resolve comptime value",54 ":2:22: error: unable to resolve comptime value",
55 ":5:26: error: unable to resolve comptime value",55 ":5:26: error: unable to resolve comptime value",
56 });56 });
57 }57 }
...@@ -62,7 +62,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -62,7 +62,7 @@ pub fn addCases(ctx: *TestContext) !void {
62 case.addCompareOutput(62 case.addCompareOutput(
63 \\extern fn printf(format: [*:0]const u8, ...) c_int;63 \\extern fn printf(format: [*:0]const u8, ...) c_int;
64 \\64 \\
65 \\export fn main() c_int {65 \\pub export fn main() c_int {
66 \\ _ = printf("Hello, %s!\n", "world");66 \\ _ = printf("Hello, %s!\n", "world");
67 \\ return 0;67 \\ return 0;
68 \\}68 \\}
...@@ -119,14 +119,14 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -119,14 +119,14 @@ pub fn addCases(ctx: *TestContext) !void {
119 \\ unreachable;119 \\ unreachable;
120 \\}120 \\}
121 \\121 \\
122 \\export fn main() c_int {122 \\pub export fn main() c_int {
123 \\ exitGood();123 \\ exitGood();
124 \\}124 \\}
125 , "");125 , "");
126126
127 // Pass a usize parameter to exit127 // Pass a usize parameter to exit
128 case.addCompareOutput(128 case.addCompareOutput(
129 \\export fn main() c_int {129 \\pub export fn main() c_int {
130 \\ exit(0);130 \\ exit(0);
131 \\}131 \\}
132 \\132 \\
...@@ -142,7 +142,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -142,7 +142,7 @@ pub fn addCases(ctx: *TestContext) !void {
142142
143 // Change the parameter to u8143 // Change the parameter to u8
144 case.addCompareOutput(144 case.addCompareOutput(
145 \\export fn main() c_int {145 \\pub export fn main() c_int {
146 \\ exit(0);146 \\ exit(0);
147 \\}147 \\}
148 \\148 \\
...@@ -158,7 +158,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -158,7 +158,7 @@ pub fn addCases(ctx: *TestContext) !void {
158158
159 // Do some arithmetic at the exit callsite159 // Do some arithmetic at the exit callsite
160 case.addCompareOutput(160 case.addCompareOutput(
161 \\export fn main() c_int {161 \\pub export fn main() c_int {
162 \\ exitMath(1);162 \\ exitMath(1);
163 \\}163 \\}
164 \\164 \\
...@@ -179,7 +179,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -179,7 +179,7 @@ pub fn addCases(ctx: *TestContext) !void {
179179
180 // Invert the arithmetic180 // Invert the arithmetic
181 case.addCompareOutput(181 case.addCompareOutput(
182 \\export fn main() c_int {182 \\pub export fn main() c_int {
183 \\ exitMath(1);183 \\ exitMath(1);
184 \\}184 \\}
185 \\185 \\
...@@ -211,7 +211,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -211,7 +211,7 @@ pub fn addCases(ctx: *TestContext) !void {
211 \\ return add(a, b);211 \\ return add(a, b);
212 \\}212 \\}
213 \\213 \\
214 \\export fn main() c_int {214 \\pub export fn main() c_int {
215 \\ return addIndirect(1, 2) - 3;215 \\ return addIndirect(1, 2) - 3;
216 \\}216 \\}
217 , "");217 , "");
...@@ -225,7 +225,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -225,7 +225,7 @@ pub fn addCases(ctx: *TestContext) !void {
225 \\ return a + b;225 \\ return a + b;
226 \\}226 \\}
227 \\227 \\
228 \\export fn main() c_int {228 \\pub export fn main() c_int {
229 \\ const x = add(1, 2);229 \\ const x = add(1, 2);
230 \\ var y = add(3, 0);230 \\ var y = add(3, 0);
231 \\ y -= x;231 \\ y -= x;
...@@ -233,11 +233,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -233,11 +233,15 @@ pub fn addCases(ctx: *TestContext) !void {
233 \\}233 \\}
234 , "");234 , "");
235 }235 }
236 {236 // This will make a pretty deep call stack, so this test can only be enabled
237 // on hosts where Zig's linking strategy can honor the 16 MiB (default) we
238 // link the self-hosted compiler with.
239 const host_supports_custom_stack_size = @import("builtin").target.os.tag == .linux;
240 if (host_supports_custom_stack_size) {
237 var case = ctx.exeFromCompiledC("@setEvalBranchQuota", .{});241 var case = ctx.exeFromCompiledC("@setEvalBranchQuota", .{});
238242
239 case.addCompareOutput(243 case.addCompareOutput(
240 \\export fn main() i32 {244 \\pub export fn main() i32 {
241 \\ @setEvalBranchQuota(1001);245 \\ @setEvalBranchQuota(1001);
242 \\ const y = rec(1001);246 \\ const y = rec(1001);
243 \\ return y - 1;247 \\ return y - 1;
...@@ -254,14 +258,14 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -254,14 +258,14 @@ pub fn addCases(ctx: *TestContext) !void {
254258
255 // Simple while loop259 // Simple while loop
256 case.addCompareOutput(260 case.addCompareOutput(
257 \\export fn main() c_int {261 \\pub export fn main() c_int {
258 \\ var a: c_int = 0;262 \\ var a: c_int = 0;
259 \\ while (a < 5) : (a+=1) {}263 \\ while (a < 5) : (a+=1) {}
260 \\ return a - 5;264 \\ return a - 5;
261 \\}265 \\}
262 , "");266 , "");
263 case.addCompareOutput(267 case.addCompareOutput(
264 \\export fn main() c_int {268 \\pub export fn main() c_int {
265 \\ var a = true;269 \\ var a = true;
266 \\ while (!a) {}270 \\ while (!a) {}
267 \\ return 0;271 \\ return 0;
...@@ -270,7 +274,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -270,7 +274,7 @@ pub fn addCases(ctx: *TestContext) !void {
270274
271 // If expression275 // If expression
272 case.addCompareOutput(276 case.addCompareOutput(
273 \\export fn main() c_int {277 \\pub export fn main() c_int {
274 \\ var cond: c_int = 0;278 \\ var cond: c_int = 0;
275 \\ var a: c_int = @as(c_int, if (cond == 0)279 \\ var a: c_int = @as(c_int, if (cond == 0)
276 \\ 2280 \\ 2
...@@ -282,7 +286,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -282,7 +286,7 @@ pub fn addCases(ctx: *TestContext) !void {
282286
283 // If expression with breakpoint that does not get hit287 // If expression with breakpoint that does not get hit
284 case.addCompareOutput(288 case.addCompareOutput(
285 \\export fn main() c_int {289 \\pub export fn main() c_int {
286 \\ var x: i32 = 1;290 \\ var x: i32 = 1;
287 \\ if (x != 1) @breakpoint();291 \\ if (x != 1) @breakpoint();
288 \\ return 0;292 \\ return 0;
...@@ -291,7 +295,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -291,7 +295,7 @@ pub fn addCases(ctx: *TestContext) !void {
291295
292 // Switch expression296 // Switch expression
293 case.addCompareOutput(297 case.addCompareOutput(
294 \\export fn main() c_int {298 \\pub export fn main() c_int {
295 \\ var cond: c_int = 0;299 \\ var cond: c_int = 0;
296 \\ var a: c_int = switch (cond) {300 \\ var a: c_int = switch (cond) {
297 \\ 1 => 1,301 \\ 1 => 1,
...@@ -306,7 +310,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -306,7 +310,7 @@ pub fn addCases(ctx: *TestContext) !void {
306310
307 // Switch expression missing else case.311 // Switch expression missing else case.
308 case.addError(312 case.addError(
309 \\export fn main() c_int {313 \\pub export fn main() c_int {
310 \\ var cond: c_int = 0;314 \\ var cond: c_int = 0;
311 \\ const a: c_int = switch (cond) {315 \\ const a: c_int = switch (cond) {
312 \\ 1 => 1,316 \\ 1 => 1,
...@@ -320,7 +324,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -320,7 +324,7 @@ pub fn addCases(ctx: *TestContext) !void {
320324
321 // Switch expression, has an unreachable prong.325 // Switch expression, has an unreachable prong.
322 case.addCompareOutput(326 case.addCompareOutput(
323 \\export fn main() c_int {327 \\pub export fn main() c_int {
324 \\ var cond: c_int = 0;328 \\ var cond: c_int = 0;
325 \\ const a: c_int = switch (cond) {329 \\ const a: c_int = switch (cond) {
326 \\ 1 => 1,330 \\ 1 => 1,
...@@ -337,7 +341,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -337,7 +341,7 @@ pub fn addCases(ctx: *TestContext) !void {
337 // Switch expression, has an unreachable prong and prongs write341 // Switch expression, has an unreachable prong and prongs write
338 // to result locations.342 // to result locations.
339 case.addCompareOutput(343 case.addCompareOutput(
340 \\export fn main() c_int {344 \\pub export fn main() c_int {
341 \\ var cond: c_int = 0;345 \\ var cond: c_int = 0;
342 \\ var a: c_int = switch (cond) {346 \\ var a: c_int = switch (cond) {
343 \\ 1 => 1,347 \\ 1 => 1,
...@@ -353,7 +357,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -353,7 +357,7 @@ pub fn addCases(ctx: *TestContext) !void {
353357
354 // Integer switch expression has duplicate case value.358 // Integer switch expression has duplicate case value.
355 case.addError(359 case.addError(
356 \\export fn main() c_int {360 \\pub export fn main() c_int {
357 \\ var cond: c_int = 0;361 \\ var cond: c_int = 0;
358 \\ const a: c_int = switch (cond) {362 \\ const a: c_int = switch (cond) {
359 \\ 1 => 1,363 \\ 1 => 1,
...@@ -372,7 +376,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -372,7 +376,7 @@ pub fn addCases(ctx: *TestContext) !void {
372376
373 // Boolean switch expression has duplicate case value.377 // Boolean switch expression has duplicate case value.
374 case.addError(378 case.addError(
375 \\export fn main() c_int {379 \\pub export fn main() c_int {
376 \\ var a: bool = false;380 \\ var a: bool = false;
377 \\ const b: c_int = switch (a) {381 \\ const b: c_int = switch (a) {
378 \\ false => 1,382 \\ false => 1,
...@@ -386,7 +390,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -386,7 +390,7 @@ pub fn addCases(ctx: *TestContext) !void {
386390
387 // Sparse (no range capable) switch expression has duplicate case value.391 // Sparse (no range capable) switch expression has duplicate case value.
388 case.addError(392 case.addError(
389 \\export fn main() c_int {393 \\pub export fn main() c_int {
390 \\ const A: type = i32;394 \\ const A: type = i32;
391 \\ const b: c_int = switch (A) {395 \\ const b: c_int = switch (A) {
392 \\ i32 => 1,396 \\ i32 => 1,
...@@ -402,7 +406,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -402,7 +406,7 @@ pub fn addCases(ctx: *TestContext) !void {
402406
403 // Ranges not allowed for some kinds of switches.407 // Ranges not allowed for some kinds of switches.
404 case.addError(408 case.addError(
405 \\export fn main() c_int {409 \\pub export fn main() c_int {
406 \\ const A: type = i32;410 \\ const A: type = i32;
407 \\ const b: c_int = switch (A) {411 \\ const b: c_int = switch (A) {
408 \\ i32 => 1,412 \\ i32 => 1,
...@@ -418,7 +422,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -418,7 +422,7 @@ pub fn addCases(ctx: *TestContext) !void {
418422
419 // Switch expression has unreachable else prong.423 // Switch expression has unreachable else prong.
420 case.addError(424 case.addError(
421 \\export fn main() c_int {425 \\pub export fn main() c_int {
422 \\ var a: u2 = 0;426 \\ var a: u2 = 0;
423 \\ const b: i32 = switch (a) {427 \\ const b: i32 = switch (a) {
424 \\ 0 => 10,428 \\ 0 => 10,
...@@ -437,7 +441,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -437,7 +441,7 @@ pub fn addCases(ctx: *TestContext) !void {
437441
438 // // Simple while loop442 // // Simple while loop
439 // case.addCompareOutput(443 // case.addCompareOutput(
440 // \\export fn main() c_int {444 // \\pub export fn main() c_int {
441 // \\ var count: c_int = 0;445 // \\ var count: c_int = 0;
442 // \\ var opt_ptr: ?*c_int = &count;446 // \\ var opt_ptr: ?*c_int = &count;
443 // \\ while (opt_ptr) |_| : (count += 1) {447 // \\ while (opt_ptr) |_| : (count += 1) {
...@@ -449,7 +453,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -449,7 +453,7 @@ pub fn addCases(ctx: *TestContext) !void {
449453
450 // // Same with non pointer optionals454 // // Same with non pointer optionals
451 // case.addCompareOutput(455 // case.addCompareOutput(
452 // \\export fn main() c_int {456 // \\pub export fn main() c_int {
453 // \\ var count: c_int = 0;457 // \\ var count: c_int = 0;
454 // \\ var opt_ptr: ?c_int = count;458 // \\ var opt_ptr: ?c_int = count;
455 // \\ while (opt_ptr) |_| : (count += 1) {459 // \\ while (opt_ptr) |_| : (count += 1) {
...@@ -463,7 +467,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -463,7 +467,7 @@ pub fn addCases(ctx: *TestContext) !void {
463 {467 {
464 var case = ctx.exeFromCompiledC("errors", .{});468 var case = ctx.exeFromCompiledC("errors", .{});
465 case.addCompareOutput(469 case.addCompareOutput(
466 \\export fn main() c_int {470 \\pub export fn main() c_int {
467 \\ var e1 = error.Foo;471 \\ var e1 = error.Foo;
468 \\ var e2 = error.Bar;472 \\ var e2 = error.Bar;
469 \\ assert(e1 != e2);473 \\ assert(e1 != e2);
...@@ -476,14 +480,14 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -476,14 +480,14 @@ pub fn addCases(ctx: *TestContext) !void {
476 \\}480 \\}
477 , "");481 , "");
478 case.addCompareOutput(482 case.addCompareOutput(
479 \\export fn main() c_int {483 \\pub export fn main() c_int {
480 \\ var e: anyerror!c_int = 0;484 \\ var e: anyerror!c_int = 0;
481 \\ const i = e catch 69;485 \\ const i = e catch 69;
482 \\ return i;486 \\ return i;
483 \\}487 \\}
484 , "");488 , "");
485 case.addCompareOutput(489 case.addCompareOutput(
486 \\export fn main() c_int {490 \\pub export fn main() c_int {
487 \\ var e: anyerror!c_int = error.Foo;491 \\ var e: anyerror!c_int = error.Foo;
488 \\ const i = e catch 69;492 \\ const i = e catch 69;
489 \\ return 69 - i;493 \\ return 69 - i;
...@@ -495,7 +499,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -495,7 +499,7 @@ pub fn addCases(ctx: *TestContext) !void {
495 var case = ctx.exeFromCompiledC("structs", .{});499 var case = ctx.exeFromCompiledC("structs", .{});
496 case.addError(500 case.addError(
497 \\const Point = struct { x: i32, y: i32 };501 \\const Point = struct { x: i32, y: i32 };
498 \\export fn main() c_int {502 \\pub export fn main() c_int {
499 \\ var p: Point = .{503 \\ var p: Point = .{
500 \\ .y = 24,504 \\ .y = 24,
501 \\ .x = 12,505 \\ .x = 12,
...@@ -509,19 +513,19 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -509,19 +513,19 @@ pub fn addCases(ctx: *TestContext) !void {
509 });513 });
510 case.addError(514 case.addError(
511 \\const Point = struct { x: i32, y: i32 };515 \\const Point = struct { x: i32, y: i32 };
512 \\export fn main() c_int {516 \\pub export fn main() c_int {
513 \\ var p: Point = .{517 \\ var p: Point = .{
514 \\ .y = 24,518 \\ .y = 24,
515 \\ };519 \\ };
516 \\ return p.y - p.x - p.x;520 \\ return p.y - p.x - p.x;
517 \\}521 \\}
518 , &.{522 , &.{
519 ":3:21: error: mising struct field: x",523 ":3:21: error: missing struct field: x",
520 ":1:15: note: struct 'Point' declared here",524 ":1:15: note: struct 'test_case.Point' declared here",
521 });525 });
522 case.addError(526 case.addError(
523 \\const Point = struct { x: i32, y: i32 };527 \\const Point = struct { x: i32, y: i32 };
524 \\export fn main() c_int {528 \\pub export fn main() c_int {
525 \\ var p: Point = .{529 \\ var p: Point = .{
526 \\ .x = 12,530 \\ .x = 12,
527 \\ .y = 24,531 \\ .y = 24,
...@@ -530,12 +534,12 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -530,12 +534,12 @@ pub fn addCases(ctx: *TestContext) !void {
530 \\ return p.y - p.x - p.x;534 \\ return p.y - p.x - p.x;
531 \\}535 \\}
532 , &.{536 , &.{
533 ":6:10: error: no field named 'z' in struct 'Point'",537 ":6:10: error: no field named 'z' in struct 'test_case.Point'",
534 ":1:15: note: struct declared here",538 ":1:15: note: struct declared here",
535 });539 });
536 case.addCompareOutput(540 case.addCompareOutput(
537 \\const Point = struct { x: i32, y: i32 };541 \\const Point = struct { x: i32, y: i32 };
538 \\export fn main() c_int {542 \\pub export fn main() c_int {
539 \\ var p: Point = .{543 \\ var p: Point = .{
540 \\ .x = 12,544 \\ .x = 12,
541 \\ .y = 24,545 \\ .y = 24,
...@@ -589,7 +593,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -589,7 +593,7 @@ pub fn addCases(ctx: *TestContext) !void {
589 case.addCompareOutput(593 case.addCompareOutput(
590 \\const Number = enum { One, Two, Three };594 \\const Number = enum { One, Two, Three };
591 \\595 \\
592 \\export fn main() c_int {596 \\pub export fn main() c_int {
593 \\ var number1 = Number.One;597 \\ var number1 = Number.One;
594 \\ var number2: Number = .Two;598 \\ var number2: Number = .Two;
595 \\ const number3 = @intToEnum(Number, 2);599 \\ const number3 = @intToEnum(Number, 2);
...@@ -676,7 +680,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -676,7 +680,7 @@ pub fn addCases(ctx: *TestContext) !void {
676680
677 case.addError(681 case.addError(
678 \\const E1 = enum { a, b, c, b, d };682 \\const E1 = enum { a, b, c, b, d };
679 \\export fn foo() void {683 \\pub export fn main() c_int {
680 \\ const x = E1.a;684 \\ const x = E1.a;
681 \\}685 \\}
682 , &.{686 , &.{
...@@ -685,7 +689,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -685,7 +689,7 @@ pub fn addCases(ctx: *TestContext) !void {
685 });689 });
686690
687 case.addError(691 case.addError(
688 \\export fn foo() void {692 \\pub export fn main() c_int {
689 \\ const a = true;693 \\ const a = true;
690 \\ const b = @enumToInt(a);694 \\ const b = @enumToInt(a);
691 \\}695 \\}
...@@ -694,7 +698,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -694,7 +698,7 @@ pub fn addCases(ctx: *TestContext) !void {
694 });698 });
695699
696 case.addError(700 case.addError(
697 \\export fn foo() void {701 \\pub export fn main() c_int {
698 \\ const a = 1;702 \\ const a = 1;
699 \\ const b = @intToEnum(bool, a);703 \\ const b = @intToEnum(bool, a);
700 \\}704 \\}
...@@ -704,17 +708,17 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -704,17 +708,17 @@ pub fn addCases(ctx: *TestContext) !void {
704708
705 case.addError(709 case.addError(
706 \\const E = enum { a, b, c };710 \\const E = enum { a, b, c };
707 \\export fn foo() void {711 \\pub export fn main() c_int {
708 \\ const b = @intToEnum(E, 3);712 \\ const b = @intToEnum(E, 3);
709 \\}713 \\}
710 , &.{714 , &.{
711 ":3:15: error: enum 'E' has no tag with value 3",715 ":3:15: error: enum 'test_case.E' has no tag with value 3",
712 ":1:11: note: enum declared here",716 ":1:11: note: enum declared here",
713 });717 });
714718
715 case.addError(719 case.addError(
716 \\const E = enum { a, b, c };720 \\const E = enum { a, b, c };
717 \\export fn foo() void {721 \\pub export fn main() c_int {
718 \\ var x: E = .a;722 \\ var x: E = .a;
719 \\ switch (x) {723 \\ switch (x) {
720 \\ .a => {},724 \\ .a => {},
...@@ -724,12 +728,12 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -724,12 +728,12 @@ pub fn addCases(ctx: *TestContext) !void {
724 , &.{728 , &.{
725 ":4:5: error: switch must handle all possibilities",729 ":4:5: error: switch must handle all possibilities",
726 ":4:5: note: unhandled enumeration value: 'b'",730 ":4:5: note: unhandled enumeration value: 'b'",
727 ":1:11: note: enum 'E' declared here",731 ":1:11: note: enum 'test_case.E' declared here",
728 });732 });
729733
730 case.addError(734 case.addError(
731 \\const E = enum { a, b, c };735 \\const E = enum { a, b, c };
732 \\export fn foo() void {736 \\pub export fn main() c_int {
733 \\ var x: E = .a;737 \\ var x: E = .a;
734 \\ switch (x) {738 \\ switch (x) {
735 \\ .a => {},739 \\ .a => {},
...@@ -745,7 +749,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -745,7 +749,7 @@ pub fn addCases(ctx: *TestContext) !void {
745749
746 case.addError(750 case.addError(
747 \\const E = enum { a, b, c };751 \\const E = enum { a, b, c };
748 \\export fn foo() void {752 \\pub export fn main() c_int {
749 \\ var x: E = .a;753 \\ var x: E = .a;
750 \\ switch (x) {754 \\ switch (x) {
751 \\ .a => {},755 \\ .a => {},
...@@ -760,7 +764,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -760,7 +764,7 @@ pub fn addCases(ctx: *TestContext) !void {
760764
761 case.addError(765 case.addError(
762 \\const E = enum { a, b, c };766 \\const E = enum { a, b, c };
763 \\export fn foo() void {767 \\pub export fn main() c_int {
764 \\ var x: E = .a;768 \\ var x: E = .a;
765 \\ switch (x) {769 \\ switch (x) {
766 \\ .a => {},770 \\ .a => {},
...@@ -775,21 +779,21 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -775,21 +779,21 @@ pub fn addCases(ctx: *TestContext) !void {
775779
776 case.addError(780 case.addError(
777 \\const E = enum { a, b, c };781 \\const E = enum { a, b, c };
778 \\export fn foo() void {782 \\pub export fn main() c_int {
779 \\ var x = E.d;783 \\ var x = E.d;
780 \\}784 \\}
781 , &.{785 , &.{
782 ":3:14: error: enum 'E' has no member named 'd'",786 ":3:14: error: enum 'test_case.E' has no member named 'd'",
783 ":1:11: note: enum declared here",787 ":1:11: note: enum declared here",
784 });788 });
785789
786 case.addError(790 case.addError(
787 \\const E = enum { a, b, c };791 \\const E = enum { a, b, c };
788 \\export fn foo() void {792 \\pub export fn main() c_int {
789 \\ var x: E = .d;793 \\ var x: E = .d;
790 \\}794 \\}
791 , &.{795 , &.{
792 ":3:17: error: enum 'E' has no field named 'd'",796 ":3:17: error: enum 'test_case.E' has no field named 'd'",
793 ":1:11: note: enum declared here",797 ":1:11: note: enum declared here",
794 });798 });
795 }799 }
test/stage2/darwin.zig+13-9
...@@ -13,20 +13,24 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -13,20 +13,24 @@ pub fn addCases(ctx: *TestContext) !void {
13 };13 };
14 {14 {
15 var case = ctx.exe("hello world with updates", target);15 var case = ctx.exe("hello world with updates", target);
16 case.addError("", &[_][]const u8{"error: no entry point found"});16 case.addError("", &[_][]const u8{
17 ":84:9: error: struct 'test_case.test_case' has no member named 'main'",
18 });
1719
18 // Incorrect return type20 // Incorrect return type
19 case.addError(21 case.addError(
20 \\export fn main() noreturn {22 \\pub export fn main() noreturn {
21 \\}23 \\}
22 , &[_][]const u8{":2:1: error: expected noreturn, found void"});24 , &[_][]const u8{
25 ":2:1: error: expected noreturn, found void",
26 });
2327
24 // Regular old hello world28 // Regular old hello world
25 case.addCompareOutput(29 case.addCompareOutput(
26 \\extern "c" fn write(usize, usize, usize) usize;30 \\extern "c" fn write(usize, usize, usize) usize;
27 \\extern "c" fn exit(usize) noreturn;31 \\extern "c" fn exit(usize) noreturn;
28 \\32 \\
29 \\export fn main() noreturn {33 \\pub export fn main() noreturn {
30 \\ print();34 \\ print();
31 \\35 \\
32 \\ exit(0);36 \\ exit(0);
...@@ -46,7 +50,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -46,7 +50,7 @@ pub fn addCases(ctx: *TestContext) !void {
46 \\extern "c" fn write(usize, usize, usize) usize;50 \\extern "c" fn write(usize, usize, usize) usize;
47 \\extern "c" fn exit(usize) noreturn;51 \\extern "c" fn exit(usize) noreturn;
48 \\52 \\
49 \\export fn main() noreturn {53 \\pub export fn main() noreturn {
50 \\ print();54 \\ print();
51 \\ print();55 \\ print();
52 \\ print();56 \\ print();
...@@ -73,7 +77,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -73,7 +77,7 @@ pub fn addCases(ctx: *TestContext) !void {
73 \\extern "c" fn write(usize, usize, usize) usize;77 \\extern "c" fn write(usize, usize, usize) usize;
74 \\extern "c" fn exit(usize) noreturn;78 \\extern "c" fn exit(usize) noreturn;
75 \\79 \\
76 \\export fn main() noreturn {80 \\pub export fn main() noreturn {
77 \\ print();81 \\ print();
78 \\82 \\
79 \\ exit(0);83 \\ exit(0);
...@@ -93,7 +97,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -93,7 +97,7 @@ pub fn addCases(ctx: *TestContext) !void {
93 \\extern "c" fn write(usize, usize, usize) usize;97 \\extern "c" fn write(usize, usize, usize) usize;
94 \\extern "c" fn exit(usize) noreturn;98 \\extern "c" fn exit(usize) noreturn;
95 \\99 \\
96 \\export fn main() noreturn {100 \\pub export fn main() noreturn {
97 \\ print();101 \\ print();
98 \\ print();102 \\ print();
99 \\103 \\
...@@ -119,7 +123,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -119,7 +123,7 @@ pub fn addCases(ctx: *TestContext) !void {
119 case.addCompareOutput(123 case.addCompareOutput(
120 \\extern "c" fn exit(usize) noreturn;124 \\extern "c" fn exit(usize) noreturn;
121 \\125 \\
122 \\export fn main() noreturn {126 \\pub export fn main() noreturn {
123 \\ exit(0);127 \\ exit(0);
124 \\}128 \\}
125 ,129 ,
...@@ -130,7 +134,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -130,7 +134,7 @@ pub fn addCases(ctx: *TestContext) !void {
130 \\extern "c" fn exit(usize) noreturn;134 \\extern "c" fn exit(usize) noreturn;
131 \\extern "c" fn write(usize, usize, usize) usize;135 \\extern "c" fn write(usize, usize, usize) usize;
132 \\136 \\
133 \\export fn main() noreturn {137 \\pub export fn main() noreturn {
134 \\ _ = write(1, @ptrToInt("Hey!\n"), 5);138 \\ _ = write(1, @ptrToInt("Hey!\n"), 5);
135 \\ exit(0);139 \\ exit(0);
136 \\}140 \\}
test/stage2/llvm.zig+8-8
...@@ -18,7 +18,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -18,7 +18,7 @@ pub fn addCases(ctx: *TestContext) !void {
18 \\ return a + b;18 \\ return a + b;
19 \\}19 \\}
20 \\20 \\
21 \\export fn main() c_int {21 \\pub export fn main() c_int {
22 \\ var a: i32 = -5;22 \\ var a: i32 = -5;
23 \\ const x = add(a, 7);23 \\ const x = add(a, 7);
24 \\ var y = add(2, 0);24 \\ var y = add(2, 0);
...@@ -34,7 +34,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -34,7 +34,7 @@ pub fn addCases(ctx: *TestContext) !void {
34 case.addCompareOutput(34 case.addCompareOutput(
35 \\extern fn puts(s: [*:0]const u8) c_int;35 \\extern fn puts(s: [*:0]const u8) c_int;
36 \\36 \\
37 \\export fn main() c_int {37 \\pub export fn main() c_int {
38 \\ _ = puts("hello world!");38 \\ _ = puts("hello world!");
39 \\ return 0;39 \\ return 0;
40 \\}40 \\}
...@@ -53,7 +53,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -53,7 +53,7 @@ pub fn addCases(ctx: *TestContext) !void {
53 \\ if (!ok) unreachable;53 \\ if (!ok) unreachable;
54 \\}54 \\}
55 \\55 \\
56 \\export fn main() c_int {56 \\pub export fn main() c_int {
57 \\ assert(add(1,2) == 3);57 \\ assert(add(1,2) == 3);
58 \\ return 0;58 \\ return 0;
59 \\}59 \\}
...@@ -77,7 +77,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -77,7 +77,7 @@ pub fn addCases(ctx: *TestContext) !void {
77 \\ return val + 10;77 \\ return val + 10;
78 \\}78 \\}
79 \\79 \\
80 \\export fn main() c_int {80 \\pub export fn main() c_int {
81 \\ assert(foo(false) == 20);81 \\ assert(foo(false) == 20);
82 \\ assert(foo(true) == 30);82 \\ assert(foo(true) == 30);
83 \\ return 0;83 \\ return 0;
...@@ -104,7 +104,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -104,7 +104,7 @@ pub fn addCases(ctx: *TestContext) !void {
104 \\ return val;104 \\ return val;
105 \\}105 \\}
106 \\106 \\
107 \\export fn main() c_int {107 \\pub export fn main() c_int {
108 \\ assert(foo(false) == 10);108 \\ assert(foo(false) == 10);
109 \\ assert(foo(true) == 20);109 \\ assert(foo(true) == 20);
110 \\ return 0;110 \\ return 0;
...@@ -120,7 +120,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -120,7 +120,7 @@ pub fn addCases(ctx: *TestContext) !void {
120 \\ if (!ok) unreachable;120 \\ if (!ok) unreachable;
121 \\}121 \\}
122 \\122 \\
123 \\export fn main() c_int {123 \\pub export fn main() c_int {
124 \\ var sum: u32 = 0;124 \\ var sum: u32 = 0;
125 \\ var i: u32 = 0;125 \\ var i: u32 = 0;
126 \\ while (i < 5) : (i += 1) {126 \\ while (i < 5) : (i += 1) {
...@@ -141,7 +141,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -141,7 +141,7 @@ pub fn addCases(ctx: *TestContext) !void {
141 \\ if (!ok) unreachable;141 \\ if (!ok) unreachable;
142 \\}142 \\}
143 \\143 \\
144 \\export fn main() c_int {144 \\pub export fn main() c_int {
145 \\ var opt_val: ?i32 = 10;145 \\ var opt_val: ?i32 = 10;
146 \\ var null_val: ?i32 = null;146 \\ var null_val: ?i32 = null;
147 \\147 \\
...@@ -190,7 +190,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -190,7 +190,7 @@ pub fn addCases(ctx: *TestContext) !void {
190 \\ if (!ok) unreachable;190 \\ if (!ok) unreachable;
191 \\}191 \\}
192 \\192 \\
193 \\export fn main() c_int {193 \\pub export fn main() c_int {
194 \\ var x: u32 = 0;194 \\ var x: u32 = 0;
195 \\ for ("hello") |_| {195 \\ for ("hello") |_| {
196 \\ x += 1;196 \\ x += 1;
test/stage2/riscv64.zig+1-1
...@@ -11,7 +11,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -11,7 +11,7 @@ pub fn addCases(ctx: *TestContext) !void {
11 var case = ctx.exe("riscv64 hello world", linux_riscv64);11 var case = ctx.exe("riscv64 hello world", linux_riscv64);
12 // Regular old hello world12 // Regular old hello world
13 case.addCompareOutput(13 case.addCompareOutput(
14 \\export fn _start() noreturn {14 \\pub export fn _start() noreturn {
15 \\ print();15 \\ print();
16 \\16 \\
17 \\ exit();17 \\ exit();
test/stage2/spu-ii.zig deleted-23
...@@ -1,23 +0,0 @@
1const std = @import("std");
2const TestContext = @import("../../src/test.zig").TestContext;
3
4const spu = std.zig.CrossTarget{
5 .cpu_arch = .spu_2,
6 .os_tag = .freestanding,
7};
8
9pub fn addCases(ctx: *TestContext) !void {
10 {
11 var case = ctx.exe("SPU-II Basic Test", spu);
12 case.addCompareOutput(
13 \\fn killEmulator() noreturn {
14 \\ asm volatile ("undefined0");
15 \\ unreachable;
16 \\}
17 \\
18 \\export fn _start() noreturn {
19 \\ killEmulator();
20 \\}
21 , "");
22 }
23}
test/stage2/test.zig+144-492
...@@ -13,7 +13,6 @@ const linux_x64 = std.zig.CrossTarget{...@@ -13,7 +13,6 @@ const linux_x64 = std.zig.CrossTarget{
1313
14pub fn addCases(ctx: *TestContext) !void {14pub fn addCases(ctx: *TestContext) !void {
15 try @import("cbe.zig").addCases(ctx);15 try @import("cbe.zig").addCases(ctx);
16 try @import("spu-ii.zig").addCases(ctx);
17 try @import("arm.zig").addCases(ctx);16 try @import("arm.zig").addCases(ctx);
18 try @import("aarch64.zig").addCases(ctx);17 try @import("aarch64.zig").addCases(ctx);
19 try @import("llvm.zig").addCases(ctx);18 try @import("llvm.zig").addCases(ctx);
...@@ -24,17 +23,19 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -24,17 +23,19 @@ pub fn addCases(ctx: *TestContext) !void {
24 {23 {
25 var case = ctx.exe("hello world with updates", linux_x64);24 var case = ctx.exe("hello world with updates", linux_x64);
2625
27 case.addError("", &[_][]const u8{"error: no entry point found"});26 case.addError("", &[_][]const u8{
27 ":84:9: error: struct 'test_case.test_case' has no member named 'main'",
28 });
2829
29 // Incorrect return type30 // Incorrect return type
30 case.addError(31 case.addError(
31 \\export fn _start() noreturn {32 \\pub export fn _start() noreturn {
32 \\}33 \\}
33 , &[_][]const u8{":2:1: error: expected noreturn, found void"});34 , &[_][]const u8{":2:1: error: expected noreturn, found void"});
3435
35 // Regular old hello world36 // Regular old hello world
36 case.addCompareOutput(37 case.addCompareOutput(
37 \\export fn _start() noreturn {38 \\pub export fn _start() noreturn {
38 \\ print();39 \\ print();
39 \\40 \\
40 \\ exit();41 \\ exit();
...@@ -64,12 +65,11 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -64,12 +65,11 @@ pub fn addCases(ctx: *TestContext) !void {
64 ,65 ,
65 "Hello, World!\n",66 "Hello, World!\n",
66 );67 );
67 // Now change the message only68
69 // Convert to pub fn main
68 case.addCompareOutput(70 case.addCompareOutput(
69 \\export fn _start() noreturn {71 \\pub fn main() void {
70 \\ print();72 \\ print();
71 \\
72 \\ exit();
73 \\}73 \\}
74 \\74 \\
75 \\fn print() void {75 \\fn print() void {
...@@ -77,32 +77,41 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -77,32 +77,41 @@ pub fn addCases(ctx: *TestContext) !void {
77 \\ :77 \\ :
78 \\ : [number] "{rax}" (1),78 \\ : [number] "{rax}" (1),
79 \\ [arg1] "{rdi}" (1),79 \\ [arg1] "{rdi}" (1),
80 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),80 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
81 \\ [arg3] "{rdx}" (104)81 \\ [arg3] "{rdx}" (14)
82 \\ : "rcx", "r11", "memory"82 \\ : "rcx", "r11", "memory"
83 \\ );83 \\ );
84 \\ return;84 \\ return;
85 \\}85 \\}
86 ,
87 "Hello, World!\n",
88 );
89
90 // Now change the message only
91 case.addCompareOutput(
92 \\pub fn main() void {
93 \\ print();
94 \\}
86 \\95 \\
87 \\fn exit() noreturn {96 \\fn print() void {
88 \\ asm volatile ("syscall"97 \\ asm volatile ("syscall"
89 \\ :98 \\ :
90 \\ : [number] "{rax}" (231),99 \\ : [number] "{rax}" (1),
91 \\ [arg1] "{rdi}" (0)100 \\ [arg1] "{rdi}" (1),
101 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
102 \\ [arg3] "{rdx}" (104)
92 \\ : "rcx", "r11", "memory"103 \\ : "rcx", "r11", "memory"
93 \\ );104 \\ );
94 \\ unreachable;105 \\ return;
95 \\}106 \\}
96 ,107 ,
97 "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",108 "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
98 );109 );
99 // Now we print it twice.110 // Now we print it twice.
100 case.addCompareOutput(111 case.addCompareOutput(
101 \\export fn _start() noreturn {112 \\pub fn main() void {
102 \\ print();113 \\ print();
103 \\ print();114 \\ print();
104 \\
105 \\ exit();
106 \\}115 \\}
107 \\116 \\
108 \\fn print() void {117 \\fn print() void {
...@@ -116,16 +125,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -116,16 +125,6 @@ pub fn addCases(ctx: *TestContext) !void {
116 \\ );125 \\ );
117 \\ return;126 \\ return;
118 \\}127 \\}
119 \\
120 \\fn exit() noreturn {
121 \\ asm volatile ("syscall"
122 \\ :
123 \\ : [number] "{rax}" (231),
124 \\ [arg1] "{rdi}" (0)
125 \\ : "rcx", "r11", "memory"
126 \\ );
127 \\ unreachable;
128 \\}
129 ,128 ,
130 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.129 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
131 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.130 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
...@@ -136,7 +135,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -136,7 +135,7 @@ pub fn addCases(ctx: *TestContext) !void {
136 {135 {
137 var case = ctx.exe("adding numbers at comptime", linux_x64);136 var case = ctx.exe("adding numbers at comptime", linux_x64);
138 case.addCompareOutput(137 case.addCompareOutput(
139 \\export fn _start() noreturn {138 \\pub export fn _start() noreturn {
140 \\ asm volatile ("syscall"139 \\ asm volatile ("syscall"
141 \\ :140 \\ :
142 \\ : [number] "{rax}" (1),141 \\ : [number] "{rax}" (1),
...@@ -161,7 +160,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -161,7 +160,7 @@ pub fn addCases(ctx: *TestContext) !void {
161 {160 {
162 var case = ctx.exe("adding numbers at runtime and comptime", linux_x64);161 var case = ctx.exe("adding numbers at runtime and comptime", linux_x64);
163 case.addCompareOutput(162 case.addCompareOutput(
164 \\export fn _start() noreturn {163 \\pub export fn _start() noreturn {
165 \\ add(3, 4);164 \\ add(3, 4);
166 \\165 \\
167 \\ exit();166 \\ exit();
...@@ -185,7 +184,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -185,7 +184,7 @@ pub fn addCases(ctx: *TestContext) !void {
185 );184 );
186 // comptime function call185 // comptime function call
187 case.addCompareOutput(186 case.addCompareOutput(
188 \\export fn _start() noreturn {187 \\pub export fn _start() noreturn {
189 \\ exit();188 \\ exit();
190 \\}189 \\}
191 \\190 \\
...@@ -209,7 +208,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -209,7 +208,7 @@ pub fn addCases(ctx: *TestContext) !void {
209 );208 );
210 // Inline function call209 // Inline function call
211 case.addCompareOutput(210 case.addCompareOutput(
212 \\export fn _start() noreturn {211 \\pub export fn _start() noreturn {
213 \\ var x: usize = 3;212 \\ var x: usize = 3;
214 \\ const y = add(1, 2, x);213 \\ const y = add(1, 2, x);
215 \\ exit(y - 6);214 \\ exit(y - 6);
...@@ -236,25 +235,13 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -236,25 +235,13 @@ pub fn addCases(ctx: *TestContext) !void {
236 {235 {
237 var case = ctx.exe("subtracting numbers at runtime", linux_x64);236 var case = ctx.exe("subtracting numbers at runtime", linux_x64);
238 case.addCompareOutput(237 case.addCompareOutput(
239 \\export fn _start() noreturn {238 \\pub fn main() void {
240 \\ sub(7, 4);239 \\ sub(7, 4);
241 \\
242 \\ exit();
243 \\}240 \\}
244 \\241 \\
245 \\fn sub(a: u32, b: u32) void {242 \\fn sub(a: u32, b: u32) void {
246 \\ if (a - b != 3) unreachable;243 \\ if (a - b != 3) unreachable;
247 \\}244 \\}
248 \\
249 \\fn exit() noreturn {
250 \\ asm volatile ("syscall"
251 \\ :
252 \\ : [number] "{rax}" (231),
253 \\ [arg1] "{rdi}" (0)
254 \\ : "rcx", "r11", "memory"
255 \\ );
256 \\ unreachable;
257 \\}
258 ,245 ,
259 "",246 "",
260 );247 );
...@@ -262,58 +249,33 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -262,58 +249,33 @@ pub fn addCases(ctx: *TestContext) !void {
262 {249 {
263 var case = ctx.exe("@TypeOf", linux_x64);250 var case = ctx.exe("@TypeOf", linux_x64);
264 case.addCompareOutput(251 case.addCompareOutput(
265 \\export fn _start() noreturn {252 \\pub fn main() void {
266 \\ var x: usize = 0;253 \\ var x: usize = 0;
267 \\ const z = @TypeOf(x, @as(u128, 5));254 \\ const z = @TypeOf(x, @as(u128, 5));
268 \\ assert(z == u128);255 \\ assert(z == u128);
269 \\
270 \\ exit();
271 \\}256 \\}
272 \\257 \\
273 \\pub fn assert(ok: bool) void {258 \\pub fn assert(ok: bool) void {
274 \\ if (!ok) unreachable; // assertion failure259 \\ if (!ok) unreachable; // assertion failure
275 \\}260 \\}
276 \\
277 \\fn exit() noreturn {
278 \\ asm volatile ("syscall"
279 \\ :
280 \\ : [number] "{rax}" (231),
281 \\ [arg1] "{rdi}" (0)
282 \\ : "rcx", "r11", "memory"
283 \\ );
284 \\ unreachable;
285 \\}
286 ,261 ,
287 "",262 "",
288 );263 );
289 case.addCompareOutput(264 case.addCompareOutput(
290 \\export fn _start() noreturn {265 \\pub fn main() void {
291 \\ const z = @TypeOf(true);266 \\ const z = @TypeOf(true);
292 \\ assert(z == bool);267 \\ assert(z == bool);
293 \\
294 \\ exit();
295 \\}268 \\}
296 \\269 \\
297 \\pub fn assert(ok: bool) void {270 \\pub fn assert(ok: bool) void {
298 \\ if (!ok) unreachable; // assertion failure271 \\ if (!ok) unreachable; // assertion failure
299 \\}272 \\}
300 \\
301 \\fn exit() noreturn {
302 \\ asm volatile ("syscall"
303 \\ :
304 \\ : [number] "{rax}" (231),
305 \\ [arg1] "{rdi}" (0)
306 \\ : "rcx", "r11", "memory"
307 \\ );
308 \\ unreachable;
309 \\}
310 ,273 ,
311 "",274 "",
312 );275 );
313 case.addError(276 case.addError(
314 \\export fn _start() noreturn {277 \\pub fn main() void {
315 \\ const z = @TypeOf(true, 1);278 \\ const z = @TypeOf(true, 1);
316 \\ unreachable;
317 \\}279 \\}
318 , &[_][]const u8{":2:15: error: incompatible types: 'bool' and 'comptime_int'"});280 , &[_][]const u8{":2:15: error: incompatible types: 'bool' and 'comptime_int'"});
319 }281 }
...@@ -321,7 +283,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -321,7 +283,7 @@ pub fn addCases(ctx: *TestContext) !void {
321 {283 {
322 var case = ctx.exe("multiplying numbers at runtime and comptime", linux_x64);284 var case = ctx.exe("multiplying numbers at runtime and comptime", linux_x64);
323 case.addCompareOutput(285 case.addCompareOutput(
324 \\export fn _start() noreturn {286 \\pub export fn _start() noreturn {
325 \\ mul(3, 4);287 \\ mul(3, 4);
326 \\288 \\
327 \\ exit();289 \\ exit();
...@@ -345,7 +307,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -345,7 +307,7 @@ pub fn addCases(ctx: *TestContext) !void {
345 );307 );
346 // comptime function call308 // comptime function call
347 case.addCompareOutput(309 case.addCompareOutput(
348 \\export fn _start() noreturn {310 \\pub fn _start() noreturn {
349 \\ exit();311 \\ exit();
350 \\}312 \\}
351 \\313 \\
...@@ -369,7 +331,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -369,7 +331,7 @@ pub fn addCases(ctx: *TestContext) !void {
369 );331 );
370 // Inline function call332 // Inline function call
371 case.addCompareOutput(333 case.addCompareOutput(
372 \\export fn _start() noreturn {334 \\pub export fn _start() noreturn {
373 \\ var x: usize = 5;335 \\ var x: usize = 5;
374 \\ const y = mul(2, 3, x);336 \\ const y = mul(2, 3, x);
375 \\ exit(y - 30);337 \\ exit(y - 30);
...@@ -396,10 +358,8 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -396,10 +358,8 @@ pub fn addCases(ctx: *TestContext) !void {
396 {358 {
397 var case = ctx.exe("assert function", linux_x64);359 var case = ctx.exe("assert function", linux_x64);
398 case.addCompareOutput(360 case.addCompareOutput(
399 \\export fn _start() noreturn {361 \\pub fn main() void {
400 \\ add(3, 4);362 \\ add(3, 4);
401 \\
402 \\ exit();
403 \\}363 \\}
404 \\364 \\
405 \\fn add(a: u32, b: u32) void {365 \\fn add(a: u32, b: u32) void {
...@@ -426,10 +386,8 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -426,10 +386,8 @@ pub fn addCases(ctx: *TestContext) !void {
426 // Tests copying a register. For the `c = a + b`, it has to386 // Tests copying a register. For the `c = a + b`, it has to
427 // preserve both a and b, because they are both used later.387 // preserve both a and b, because they are both used later.
428 case.addCompareOutput(388 case.addCompareOutput(
429 \\export fn _start() noreturn {389 \\pub fn main() void {
430 \\ add(3, 4);390 \\ add(3, 4);
431 \\
432 \\ exit();
433 \\}391 \\}
434 \\392 \\
435 \\fn add(a: u32, b: u32) void {393 \\fn add(a: u32, b: u32) void {
...@@ -442,26 +400,14 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -442,26 +400,14 @@ pub fn addCases(ctx: *TestContext) !void {
442 \\pub fn assert(ok: bool) void {400 \\pub fn assert(ok: bool) void {
443 \\ if (!ok) unreachable; // assertion failure401 \\ if (!ok) unreachable; // assertion failure
444 \\}402 \\}
445 \\
446 \\fn exit() noreturn {
447 \\ asm volatile ("syscall"
448 \\ :
449 \\ : [number] "{rax}" (231),
450 \\ [arg1] "{rdi}" (0)
451 \\ : "rcx", "r11", "memory"
452 \\ );
453 \\ unreachable;
454 \\}
455 ,403 ,
456 "",404 "",
457 );405 );
458406
459 // More stress on the liveness detection.407 // More stress on the liveness detection.
460 case.addCompareOutput(408 case.addCompareOutput(
461 \\export fn _start() noreturn {409 \\pub fn main() void {
462 \\ add(3, 4);410 \\ add(3, 4);
463 \\
464 \\ exit();
465 \\}411 \\}
466 \\412 \\
467 \\fn add(a: u32, b: u32) void {413 \\fn add(a: u32, b: u32) void {
...@@ -478,26 +424,14 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -478,26 +424,14 @@ pub fn addCases(ctx: *TestContext) !void {
478 \\pub fn assert(ok: bool) void {424 \\pub fn assert(ok: bool) void {
479 \\ if (!ok) unreachable; // assertion failure425 \\ if (!ok) unreachable; // assertion failure
480 \\}426 \\}
481 \\
482 \\fn exit() noreturn {
483 \\ asm volatile ("syscall"
484 \\ :
485 \\ : [number] "{rax}" (231),
486 \\ [arg1] "{rdi}" (0)
487 \\ : "rcx", "r11", "memory"
488 \\ );
489 \\ unreachable;
490 \\}
491 ,427 ,
492 "",428 "",
493 );429 );
494430
495 // Requires a second move. The register allocator should figure out to re-use rax.431 // Requires a second move. The register allocator should figure out to re-use rax.
496 case.addCompareOutput(432 case.addCompareOutput(
497 \\export fn _start() noreturn {433 \\pub fn main() void {
498 \\ add(3, 4);434 \\ add(3, 4);
499 \\
500 \\ exit();
501 \\}435 \\}
502 \\436 \\
503 \\fn add(a: u32, b: u32) void {437 \\fn add(a: u32, b: u32) void {
...@@ -515,27 +449,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -515,27 +449,15 @@ pub fn addCases(ctx: *TestContext) !void {
515 \\pub fn assert(ok: bool) void {449 \\pub fn assert(ok: bool) void {
516 \\ if (!ok) unreachable; // assertion failure450 \\ if (!ok) unreachable; // assertion failure
517 \\}451 \\}
518 \\
519 \\fn exit() noreturn {
520 \\ asm volatile ("syscall"
521 \\ :
522 \\ : [number] "{rax}" (231),
523 \\ [arg1] "{rdi}" (0)
524 \\ : "rcx", "r11", "memory"
525 \\ );
526 \\ unreachable;
527 \\}
528 ,452 ,
529 "",453 "",
530 );454 );
531455
532 // Now we test integer return values.456 // Now we test integer return values.
533 case.addCompareOutput(457 case.addCompareOutput(
534 \\export fn _start() noreturn {458 \\pub fn main() void {
535 \\ assert(add(3, 4) == 7);459 \\ assert(add(3, 4) == 7);
536 \\ assert(add(20, 10) == 30);460 \\ assert(add(20, 10) == 30);
537 \\
538 \\ exit();
539 \\}461 \\}
540 \\462 \\
541 \\fn add(a: u32, b: u32) u32 {463 \\fn add(a: u32, b: u32) u32 {
...@@ -545,27 +467,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -545,27 +467,15 @@ pub fn addCases(ctx: *TestContext) !void {
545 \\pub fn assert(ok: bool) void {467 \\pub fn assert(ok: bool) void {
546 \\ if (!ok) unreachable; // assertion failure468 \\ if (!ok) unreachable; // assertion failure
547 \\}469 \\}
548 \\
549 \\fn exit() noreturn {
550 \\ asm volatile ("syscall"
551 \\ :
552 \\ : [number] "{rax}" (231),
553 \\ [arg1] "{rdi}" (0)
554 \\ : "rcx", "r11", "memory"
555 \\ );
556 \\ unreachable;
557 \\}
558 ,470 ,
559 "",471 "",
560 );472 );
561473
562 // Local mutable variables.474 // Local mutable variables.
563 case.addCompareOutput(475 case.addCompareOutput(
564 \\export fn _start() noreturn {476 \\pub fn main() void {
565 \\ assert(add(3, 4) == 7);477 \\ assert(add(3, 4) == 7);
566 \\ assert(add(20, 10) == 30);478 \\ assert(add(20, 10) == 30);
567 \\
568 \\ exit();
569 \\}479 \\}
570 \\480 \\
571 \\fn add(a: u32, b: u32) u32 {481 \\fn add(a: u32, b: u32) u32 {
...@@ -579,39 +489,17 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -579,39 +489,17 @@ pub fn addCases(ctx: *TestContext) !void {
579 \\pub fn assert(ok: bool) void {489 \\pub fn assert(ok: bool) void {
580 \\ if (!ok) unreachable; // assertion failure490 \\ if (!ok) unreachable; // assertion failure
581 \\}491 \\}
582 \\
583 \\fn exit() noreturn {
584 \\ asm volatile ("syscall"
585 \\ :
586 \\ : [number] "{rax}" (231),
587 \\ [arg1] "{rdi}" (0)
588 \\ : "rcx", "r11", "memory"
589 \\ );
590 \\ unreachable;
591 \\}
592 ,492 ,
593 "",493 "",
594 );494 );
595495
596 // Optionals496 // Optionals
597 case.addCompareOutput(497 case.addCompareOutput(
598 \\export fn _start() noreturn {498 \\pub fn main() void {
599 \\ const a: u32 = 2;499 \\ const a: u32 = 2;
600 \\ const b: ?u32 = a;500 \\ const b: ?u32 = a;
601 \\ const c = b.?;501 \\ const c = b.?;
602 \\ if (c != 2) unreachable;502 \\ if (c != 2) unreachable;
603 \\
604 \\ exit();
605 \\}
606 \\
607 \\fn exit() noreturn {
608 \\ asm volatile ("syscall"
609 \\ :
610 \\ : [number] "{rax}" (231),
611 \\ [arg1] "{rdi}" (0)
612 \\ : "rcx", "r11", "memory"
613 \\ );
614 \\ unreachable;
615 \\}503 \\}
616 ,504 ,
617 "",505 "",
...@@ -619,12 +507,10 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -619,12 +507,10 @@ pub fn addCases(ctx: *TestContext) !void {
619507
620 // While loops508 // While loops
621 case.addCompareOutput(509 case.addCompareOutput(
622 \\export fn _start() noreturn {510 \\pub fn main() void {
623 \\ var i: u32 = 0;511 \\ var i: u32 = 0;
624 \\ while (i < 4) : (i += 1) print();512 \\ while (i < 4) : (i += 1) print();
625 \\ assert(i == 4);513 \\ assert(i == 4);
626 \\
627 \\ exit();
628 \\}514 \\}
629 \\515 \\
630 \\fn print() void {516 \\fn print() void {
...@@ -642,28 +528,16 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -642,28 +528,16 @@ pub fn addCases(ctx: *TestContext) !void {
642 \\pub fn assert(ok: bool) void {528 \\pub fn assert(ok: bool) void {
643 \\ if (!ok) unreachable; // assertion failure529 \\ if (!ok) unreachable; // assertion failure
644 \\}530 \\}
645 \\
646 \\fn exit() noreturn {
647 \\ asm volatile ("syscall"
648 \\ :
649 \\ : [number] "{rax}" (231),
650 \\ [arg1] "{rdi}" (0)
651 \\ : "rcx", "r11", "memory"
652 \\ );
653 \\ unreachable;
654 \\}
655 ,531 ,
656 "hello\nhello\nhello\nhello\n",532 "hello\nhello\nhello\nhello\n",
657 );533 );
658534
659 // inline while requires the condition to be comptime known.535 // inline while requires the condition to be comptime known.
660 case.addError(536 case.addError(
661 \\export fn _start() noreturn {537 \\pub fn main() void {
662 \\ var i: u32 = 0;538 \\ var i: u32 = 0;
663 \\ inline while (i < 4) : (i += 1) print();539 \\ inline while (i < 4) : (i += 1) print();
664 \\ assert(i == 4);540 \\ assert(i == 4);
665 \\
666 \\ exit();
667 \\}541 \\}
668 \\542 \\
669 \\fn print() void {543 \\fn print() void {
...@@ -681,24 +555,12 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -681,24 +555,12 @@ pub fn addCases(ctx: *TestContext) !void {
681 \\pub fn assert(ok: bool) void {555 \\pub fn assert(ok: bool) void {
682 \\ if (!ok) unreachable; // assertion failure556 \\ if (!ok) unreachable; // assertion failure
683 \\}557 \\}
684 \\
685 \\fn exit() noreturn {
686 \\ asm volatile ("syscall"
687 \\ :
688 \\ : [number] "{rax}" (231),
689 \\ [arg1] "{rdi}" (0)
690 \\ : "rcx", "r11", "memory"
691 \\ );
692 \\ unreachable;
693 \\}
694 , &[_][]const u8{":3:21: error: unable to resolve comptime value"});558 , &[_][]const u8{":3:21: error: unable to resolve comptime value"});
695559
696 // Labeled blocks (no conditional branch)560 // Labeled blocks (no conditional branch)
697 case.addCompareOutput(561 case.addCompareOutput(
698 \\export fn _start() noreturn {562 \\pub fn main() void {
699 \\ assert(add(3, 4) == 20);563 \\ assert(add(3, 4) == 20);
700 \\
701 \\ exit();
702 \\}564 \\}
703 \\565 \\
704 \\fn add(a: u32, b: u32) u32 {566 \\fn add(a: u32, b: u32) u32 {
...@@ -716,26 +578,14 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -716,26 +578,14 @@ pub fn addCases(ctx: *TestContext) !void {
716 \\pub fn assert(ok: bool) void {578 \\pub fn assert(ok: bool) void {
717 \\ if (!ok) unreachable; // assertion failure579 \\ if (!ok) unreachable; // assertion failure
718 \\}580 \\}
719 \\
720 \\fn exit() noreturn {
721 \\ asm volatile ("syscall"
722 \\ :
723 \\ : [number] "{rax}" (231),
724 \\ [arg1] "{rdi}" (0)
725 \\ : "rcx", "r11", "memory"
726 \\ );
727 \\ unreachable;
728 \\}
729 ,581 ,
730 "",582 "",
731 );583 );
732584
733 // This catches a possible bug in the logic for re-using dying operands.585 // This catches a possible bug in the logic for re-using dying operands.
734 case.addCompareOutput(586 case.addCompareOutput(
735 \\export fn _start() noreturn {587 \\pub fn main() void {
736 \\ assert(add(3, 4) == 116);588 \\ assert(add(3, 4) == 116);
737 \\
738 \\ exit();
739 \\}589 \\}
740 \\590 \\
741 \\fn add(a: u32, b: u32) u32 {591 \\fn add(a: u32, b: u32) u32 {
...@@ -758,27 +608,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -758,27 +608,15 @@ pub fn addCases(ctx: *TestContext) !void {
758 \\pub fn assert(ok: bool) void {608 \\pub fn assert(ok: bool) void {
759 \\ if (!ok) unreachable; // assertion failure609 \\ if (!ok) unreachable; // assertion failure
760 \\}610 \\}
761 \\
762 \\fn exit() noreturn {
763 \\ asm volatile ("syscall"
764 \\ :
765 \\ : [number] "{rax}" (231),
766 \\ [arg1] "{rdi}" (0)
767 \\ : "rcx", "r11", "memory"
768 \\ );
769 \\ unreachable;
770 \\}
771 ,611 ,
772 "",612 "",
773 );613 );
774614
775 // Spilling registers to the stack.615 // Spilling registers to the stack.
776 case.addCompareOutput(616 case.addCompareOutput(
777 \\export fn _start() noreturn {617 \\pub fn main() void {
778 \\ assert(add(3, 4) == 1221);618 \\ assert(add(3, 4) == 1221);
779 \\ assert(mul(3, 4) == 21609);619 \\ assert(mul(3, 4) == 21609);
780 \\
781 \\ exit();
782 \\}620 \\}
783 \\621 \\
784 \\fn add(a: u32, b: u32) u32 {622 \\fn add(a: u32, b: u32) u32 {
...@@ -839,27 +677,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -839,27 +677,15 @@ pub fn addCases(ctx: *TestContext) !void {
839 \\pub fn assert(ok: bool) void {677 \\pub fn assert(ok: bool) void {
840 \\ if (!ok) unreachable; // assertion failure678 \\ if (!ok) unreachable; // assertion failure
841 \\}679 \\}
842 \\
843 \\fn exit() noreturn {
844 \\ asm volatile ("syscall"
845 \\ :
846 \\ : [number] "{rax}" (231),
847 \\ [arg1] "{rdi}" (0)
848 \\ : "rcx", "r11", "memory"
849 \\ );
850 \\ unreachable;
851 \\}
852 ,680 ,
853 "",681 "",
854 );682 );
855683
856 // Reusing the registers of dead operands playing nicely with conditional branching.684 // Reusing the registers of dead operands playing nicely with conditional branching.
857 case.addCompareOutput(685 case.addCompareOutput(
858 \\export fn _start() noreturn {686 \\pub fn main() void {
859 \\ assert(add(3, 4) == 791);687 \\ assert(add(3, 4) == 791);
860 \\ assert(add(4, 3) == 79);688 \\ assert(add(4, 3) == 79);
861 \\
862 \\ exit();
863 \\}689 \\}
864 \\690 \\
865 \\fn add(a: u32, b: u32) u32 {691 \\fn add(a: u32, b: u32) u32 {
...@@ -901,30 +727,18 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -901,30 +727,18 @@ pub fn addCases(ctx: *TestContext) !void {
901 \\pub fn assert(ok: bool) void {727 \\pub fn assert(ok: bool) void {
902 \\ if (!ok) unreachable; // assertion failure728 \\ if (!ok) unreachable; // assertion failure
903 \\}729 \\}
904 \\
905 \\fn exit() noreturn {
906 \\ asm volatile ("syscall"
907 \\ :
908 \\ : [number] "{rax}" (231),
909 \\ [arg1] "{rdi}" (0)
910 \\ : "rcx", "r11", "memory"
911 \\ );
912 \\ unreachable;
913 \\}
914 ,730 ,
915 "",731 "",
916 );732 );
917733
918 // Character literals and multiline strings.734 // Character literals and multiline strings.
919 case.addCompareOutput(735 case.addCompareOutput(
920 \\export fn _start() noreturn {736 \\pub fn main() void {
921 \\ const ignore =737 \\ const ignore =
922 \\ \\ cool thx738 \\ \\ cool thx
923 \\ \\739 \\ \\
924 \\ ;740 \\ ;
925 \\ add('ぁ', '\x03');741 \\ add('ぁ', '\x03');
926 \\
927 \\ exit();
928 \\}742 \\}
929 \\743 \\
930 \\fn add(a: u32, b: u32) void {744 \\fn add(a: u32, b: u32) void {
...@@ -934,26 +748,14 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -934,26 +748,14 @@ pub fn addCases(ctx: *TestContext) !void {
934 \\pub fn assert(ok: bool) void {748 \\pub fn assert(ok: bool) void {
935 \\ if (!ok) unreachable; // assertion failure749 \\ if (!ok) unreachable; // assertion failure
936 \\}750 \\}
937 \\
938 \\fn exit() noreturn {
939 \\ asm volatile ("syscall"
940 \\ :
941 \\ : [number] "{rax}" (231),
942 \\ [arg1] "{rdi}" (0)
943 \\ : "rcx", "r11", "memory"
944 \\ );
945 \\ unreachable;
946 \\}
947 ,751 ,
948 "",752 "",
949 );753 );
950754
951 // Global const.755 // Global const.
952 case.addCompareOutput(756 case.addCompareOutput(
953 \\export fn _start() noreturn {757 \\pub fn main() void {
954 \\ add(aa, bb);758 \\ add(aa, bb);
955 \\
956 \\ exit();
957 \\}759 \\}
958 \\760 \\
959 \\const aa = 'ぁ';761 \\const aa = 'ぁ';
...@@ -966,41 +768,19 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -966,41 +768,19 @@ pub fn addCases(ctx: *TestContext) !void {
966 \\pub fn assert(ok: bool) void {768 \\pub fn assert(ok: bool) void {
967 \\ if (!ok) unreachable; // assertion failure769 \\ if (!ok) unreachable; // assertion failure
968 \\}770 \\}
969 \\
970 \\fn exit() noreturn {
971 \\ asm volatile ("syscall"
972 \\ :
973 \\ : [number] "{rax}" (231),
974 \\ [arg1] "{rdi}" (0)
975 \\ : "rcx", "r11", "memory"
976 \\ );
977 \\ unreachable;
978 \\}
979 ,771 ,
980 "",772 "",
981 );773 );
982774
983 // Array access.775 // Array access.
984 case.addCompareOutput(776 case.addCompareOutput(
985 \\export fn _start() noreturn {777 \\pub fn main() void {
986 \\ assert("hello"[0] == 'h');778 \\ assert("hello"[0] == 'h');
987 \\
988 \\ exit();
989 \\}779 \\}
990 \\780 \\
991 \\pub fn assert(ok: bool) void {781 \\pub fn assert(ok: bool) void {
992 \\ if (!ok) unreachable; // assertion failure782 \\ if (!ok) unreachable; // assertion failure
993 \\}783 \\}
994 \\
995 \\fn exit() noreturn {
996 \\ asm volatile ("syscall"
997 \\ :
998 \\ : [number] "{rax}" (231),
999 \\ [arg1] "{rdi}" (0)
1000 \\ : "rcx", "r11", "memory"
1001 \\ );
1002 \\ unreachable;
1003 \\}
1004 ,784 ,
1005 "",785 "",
1006 );786 );
...@@ -1008,61 +788,35 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1008,61 +788,35 @@ pub fn addCases(ctx: *TestContext) !void {
1008 // Array access to a global array.788 // Array access to a global array.
1009 case.addCompareOutput(789 case.addCompareOutput(
1010 \\const hello = "hello".*;790 \\const hello = "hello".*;
1011 \\export fn _start() noreturn {791 \\pub fn main() void {
1012 \\ assert(hello[1] == 'e');792 \\ assert(hello[1] == 'e');
1013 \\
1014 \\ exit();
1015 \\}793 \\}
1016 \\794 \\
1017 \\pub fn assert(ok: bool) void {795 \\pub fn assert(ok: bool) void {
1018 \\ if (!ok) unreachable; // assertion failure796 \\ if (!ok) unreachable; // assertion failure
1019 \\}797 \\}
1020 \\
1021 \\fn exit() noreturn {
1022 \\ asm volatile ("syscall"
1023 \\ :
1024 \\ : [number] "{rax}" (231),
1025 \\ [arg1] "{rdi}" (0)
1026 \\ : "rcx", "r11", "memory"
1027 \\ );
1028 \\ unreachable;
1029 \\}
1030 ,798 ,
1031 "",799 "",
1032 );800 );
1033801
1034 // 64bit set stack802 // 64bit set stack
1035 case.addCompareOutput(803 case.addCompareOutput(
1036 \\export fn _start() noreturn {804 \\pub fn main() void {
1037 \\ var i: u64 = 0xFFEEDDCCBBAA9988;805 \\ var i: u64 = 0xFFEEDDCCBBAA9988;
1038 \\ assert(i == 0xFFEEDDCCBBAA9988);806 \\ assert(i == 0xFFEEDDCCBBAA9988);
1039 \\
1040 \\ exit();
1041 \\}807 \\}
1042 \\808 \\
1043 \\pub fn assert(ok: bool) void {809 \\pub fn assert(ok: bool) void {
1044 \\ if (!ok) unreachable; // assertion failure810 \\ if (!ok) unreachable; // assertion failure
1045 \\}811 \\}
1046 \\
1047 \\fn exit() noreturn {
1048 \\ asm volatile ("syscall"
1049 \\ :
1050 \\ : [number] "{rax}" (231),
1051 \\ [arg1] "{rdi}" (0)
1052 \\ : "rcx", "r11", "memory"
1053 \\ );
1054 \\ unreachable;
1055 \\}
1056 ,812 ,
1057 "",813 "",
1058 );814 );
1059815
1060 // Basic for loop816 // Basic for loop
1061 case.addCompareOutput(817 case.addCompareOutput(
1062 \\export fn _start() noreturn {818 \\pub fn main() void {
1063 \\ for ("hello") |_| print();819 \\ for ("hello") |_| print();
1064 \\
1065 \\ exit();
1066 \\}820 \\}
1067 \\821 \\
1068 \\fn print() void {822 \\fn print() void {
...@@ -1076,16 +830,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1076,16 +830,6 @@ pub fn addCases(ctx: *TestContext) !void {
1076 \\ );830 \\ );
1077 \\ return;831 \\ return;
1078 \\}832 \\}
1079 \\
1080 \\fn exit() noreturn {
1081 \\ asm volatile ("syscall"
1082 \\ :
1083 \\ : [number] "{rax}" (231),
1084 \\ [arg1] "{rdi}" (0)
1085 \\ : "rcx", "r11", "memory"
1086 \\ );
1087 \\ unreachable;
1088 \\}
1089 ,833 ,
1090 "hello\nhello\nhello\nhello\nhello\n",834 "hello\nhello\nhello\nhello\nhello\n",
1091 );835 );
...@@ -1094,19 +838,8 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1094,19 +838,8 @@ pub fn addCases(ctx: *TestContext) !void {
1094 {838 {
1095 var case = ctx.exe("basic import", linux_x64);839 var case = ctx.exe("basic import", linux_x64);
1096 case.addCompareOutput(840 case.addCompareOutput(
1097 \\export fn _start() noreturn {841 \\pub fn main() void {
1098 \\ @import("print.zig").print();842 \\ @import("print.zig").print();
1099 \\ exit();
1100 \\}
1101 \\
1102 \\fn exit() noreturn {
1103 \\ asm volatile ("syscall"
1104 \\ :
1105 \\ : [number] "{rax}" (231),
1106 \\ [arg1] "{rdi}" (@as(usize, 0))
1107 \\ : "rcx", "r11", "memory"
1108 \\ );
1109 \\ unreachable;
1110 \\}843 \\}
1111 ,844 ,
1112 "Hello, World!\n",845 "Hello, World!\n",
...@@ -1128,28 +861,40 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1128,28 +861,40 @@ pub fn addCases(ctx: *TestContext) !void {
1128 .path = "print.zig",861 .path = "print.zig",
1129 });862 });
1130 }863 }
864 {
865 var case = ctx.exe("redundant comptime", linux_x64);
866 case.addError(
867 \\pub fn main() void {
868 \\ var a: comptime u32 = 0;
869 \\}
870 ,
871 &.{":2:12: error: redundant comptime keyword in already comptime scope"},
872 );
873 case.addError(
874 \\pub fn main() void {
875 \\ comptime {
876 \\ var a: u32 = comptime 0;
877 \\ }
878 \\}
879 ,
880 &.{":3:22: error: redundant comptime keyword in already comptime scope"},
881 );
882 }
1131 {883 {
1132 var case = ctx.exe("import private", linux_x64);884 var case = ctx.exe("import private", linux_x64);
1133 case.addError(885 case.addError(
1134 \\export fn _start() noreturn {886 \\pub fn main() void {
1135 \\ @import("print.zig").print();887 \\ @import("print.zig").print();
1136 \\ exit();
1137 \\}
1138 \\
1139 \\fn exit() noreturn {
1140 \\ asm volatile ("syscall"
1141 \\ :
1142 \\ : [number] "{rax}" (231),
1143 \\ [arg1] "{rdi}" (@as(usize, 0))
1144 \\ : "rcx", "r11", "memory"
1145 \\ );
1146 \\ unreachable;
1147 \\}888 \\}
1148 ,889 ,
1149 &.{":2:25: error: 'print' is private"},890 &.{
891 ":2:25: error: 'print' is not marked 'pub'",
892 "print.zig:2:1: note: declared here",
893 },
1150 );894 );
1151 try case.files.append(.{895 try case.files.append(.{
1152 .src = 896 .src =
897 \\// dummy comment to make print be on line 2
1153 \\fn print() void {898 \\fn print() void {
1154 \\ asm volatile ("syscall"899 \\ asm volatile ("syscall"
1155 \\ :900 \\ :
...@@ -1166,50 +911,56 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1166,50 +911,56 @@ pub fn addCases(ctx: *TestContext) !void {
1166 });911 });
1167 }912 }
1168913
1169 ctx.compileError("function redefinition", linux_x64,914 ctx.compileError("function redeclaration", linux_x64,
1170 \\// dummy comment915 \\// dummy comment
1171 \\fn entry() void {}916 \\fn entry() void {}
1172 \\fn entry() void {}917 \\fn entry() void {}
918 \\
919 \\fn foo() void {
920 \\ var foo = 1234;
921 \\}
1173 , &[_][]const u8{922 , &[_][]const u8{
1174 ":3:4: error: redefinition of 'entry'",923 ":3:1: error: redeclaration of 'entry'",
1175 ":2:1: note: previous definition here",924 ":2:1: note: other declaration here",
925 ":6:9: error: local shadows declaration of 'foo'",
926 ":5:1: note: declared here",
1176 });927 });
1177928
1178 ctx.compileError("global variable redefinition", linux_x64,929 ctx.compileError("global variable redeclaration", linux_x64,
1179 \\// dummy comment930 \\// dummy comment
1180 \\var foo = false;931 \\var foo = false;
1181 \\var foo = true;932 \\var foo = true;
1182 , &[_][]const u8{933 , &[_][]const u8{
1183 ":3:5: error: redefinition of 'foo'",934 ":3:1: error: redeclaration of 'foo'",
1184 ":2:1: note: previous definition here",935 ":2:1: note: other declaration here",
1185 });936 });
1186937
1187 ctx.compileError("compileError", linux_x64,938 ctx.compileError("compileError", linux_x64,
1188 \\export fn _start() noreturn {939 \\export fn foo() void {
1189 \\ @compileError("this is an error");940 \\ @compileError("this is an error");
1190 \\ unreachable;
1191 \\}941 \\}
1192 , &[_][]const u8{":2:3: error: this is an error"});942 , &[_][]const u8{":2:3: error: this is an error"});
1193943
1194 {944 {
1195 var case = ctx.obj("variable shadowing", linux_x64);945 var case = ctx.obj("variable shadowing", linux_x64);
1196 case.addError(946 case.addError(
1197 \\export fn _start() noreturn {947 \\pub fn main() void {
1198 \\ var i: u32 = 10;948 \\ var i: u32 = 10;
1199 \\ var i: u32 = 10;949 \\ var i: u32 = 10;
1200 \\ unreachable;
1201 \\}950 \\}
1202 , &[_][]const u8{951 , &[_][]const u8{
1203 ":3:9: error: redefinition of 'i'",952 ":3:9: error: redeclaration of 'i'",
1204 ":2:9: note: previous definition is here",953 ":2:9: note: previously declared here",
1205 });954 });
1206 case.addError(955 case.addError(
1207 \\var testing: i64 = 10;956 \\var testing: i64 = 10;
1208 \\export fn _start() noreturn {957 \\pub fn main() void {
1209 \\ var testing: i64 = 20;958 \\ var testing: i64 = 20;
1210 \\ unreachable;
1211 \\}959 \\}
1212 , &[_][]const u8{":3:9: error: redefinition of 'testing'"});960 , &[_][]const u8{
961 ":3:9: error: local shadows declaration of 'testing'",
962 ":1:1: note: declared here",
963 });
1213 }964 }
1214965
1215 {966 {
...@@ -1273,43 +1024,19 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1273,43 +1024,19 @@ pub fn addCases(ctx: *TestContext) !void {
12731024
1274 // Break out of loop1025 // Break out of loop
1275 case.addCompareOutput(1026 case.addCompareOutput(
1276 \\export fn _start() noreturn {1027 \\pub fn main() void {
1277 \\ while (true) {1028 \\ while (true) {
1278 \\ break;1029 \\ break;
1279 \\ }1030 \\ }
1280 \\
1281 \\ exit();
1282 \\}
1283 \\
1284 \\fn exit() noreturn {
1285 \\ asm volatile ("syscall"
1286 \\ :
1287 \\ : [number] "{rax}" (231),
1288 \\ [arg1] "{rdi}" (0)
1289 \\ : "rcx", "r11", "memory"
1290 \\ );
1291 \\ unreachable;
1292 \\}1031 \\}
1293 ,1032 ,
1294 "",1033 "",
1295 );1034 );
1296 case.addCompareOutput(1035 case.addCompareOutput(
1297 \\export fn _start() noreturn {1036 \\pub fn main() void {
1298 \\ foo: while (true) {1037 \\ foo: while (true) {
1299 \\ break :foo;1038 \\ break :foo;
1300 \\ }1039 \\ }
1301 \\
1302 \\ exit();
1303 \\}
1304 \\
1305 \\fn exit() noreturn {
1306 \\ asm volatile ("syscall"
1307 \\ :
1308 \\ : [number] "{rax}" (231),
1309 \\ [arg1] "{rdi}" (0)
1310 \\ : "rcx", "r11", "memory"
1311 \\ );
1312 \\ unreachable;
1313 \\}1040 \\}
1314 ,1041 ,
1315 "",1042 "",
...@@ -1317,7 +1044,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1317,7 +1044,7 @@ pub fn addCases(ctx: *TestContext) !void {
13171044
1318 // Continue in loop1045 // Continue in loop
1319 case.addCompareOutput(1046 case.addCompareOutput(
1320 \\export fn _start() noreturn {1047 \\pub export fn _start() noreturn {
1321 \\ var i: u64 = 0;1048 \\ var i: u64 = 0;
1322 \\ while (true) : (i+=1) {1049 \\ while (true) : (i+=1) {
1323 \\ if (i == 4) exit();1050 \\ if (i == 4) exit();
...@@ -1338,7 +1065,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1338,7 +1065,7 @@ pub fn addCases(ctx: *TestContext) !void {
1338 "",1065 "",
1339 );1066 );
1340 case.addCompareOutput(1067 case.addCompareOutput(
1341 \\export fn _start() noreturn {1068 \\pub export fn _start() noreturn {
1342 \\ var i: u64 = 0;1069 \\ var i: u64 = 0;
1343 \\ foo: while (true) : (i+=1) {1070 \\ foo: while (true) : (i+=1) {
1344 \\ if (i == 4) exit();1071 \\ if (i == 4) exit();
...@@ -1390,16 +1117,18 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1390,16 +1117,18 @@ pub fn addCases(ctx: *TestContext) !void {
1390 {1117 {
1391 var case = ctx.exe("bad inferred variable type", linux_x64);1118 var case = ctx.exe("bad inferred variable type", linux_x64);
1392 case.addError(1119 case.addError(
1393 \\export fn foo() void {1120 \\pub fn main() void {
1394 \\ var x = null;1121 \\ var x = null;
1395 \\}1122 \\}
1396 , &[_][]const u8{":2:9: error: variable of type '@Type(.Null)' must be const or comptime"});1123 , &[_][]const u8{
1124 ":2:9: error: variable of type '@Type(.Null)' must be const or comptime",
1125 });
1397 }1126 }
13981127
1399 {1128 {
1400 var case = ctx.exe("compile error in inline fn call fixed", linux_x64);1129 var case = ctx.exe("compile error in inline fn call fixed", linux_x64);
1401 case.addError(1130 case.addError(
1402 \\export fn _start() noreturn {1131 \\pub export fn _start() noreturn {
1403 \\ var x: usize = 3;1132 \\ var x: usize = 3;
1404 \\ const y = add(10, 2, x);1133 \\ const y = add(10, 2, x);
1405 \\ exit(y - 6);1134 \\ exit(y - 6);
...@@ -1422,7 +1151,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1422,7 +1151,7 @@ pub fn addCases(ctx: *TestContext) !void {
1422 , &[_][]const u8{":8:18: error: bad"});1151 , &[_][]const u8{":8:18: error: bad"});
14231152
1424 case.addCompareOutput(1153 case.addCompareOutput(
1425 \\export fn _start() noreturn {1154 \\pub export fn _start() noreturn {
1426 \\ var x: usize = 3;1155 \\ var x: usize = 3;
1427 \\ const y = add(1, 2, x);1156 \\ const y = add(1, 2, x);
1428 \\ exit(y - 6);1157 \\ exit(y - 6);
...@@ -1449,7 +1178,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1449,7 +1178,7 @@ pub fn addCases(ctx: *TestContext) !void {
1449 {1178 {
1450 var case = ctx.exe("recursive inline function", linux_x64);1179 var case = ctx.exe("recursive inline function", linux_x64);
1451 case.addCompareOutput(1180 case.addCompareOutput(
1452 \\export fn _start() noreturn {1181 \\pub export fn _start() noreturn {
1453 \\ const y = fibonacci(7);1182 \\ const y = fibonacci(7);
1454 \\ exit(y - 21);1183 \\ exit(y - 21);
1455 \\}1184 \\}
...@@ -1475,7 +1204,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1475,7 +1204,7 @@ pub fn addCases(ctx: *TestContext) !void {
1475 // Without storing source locations relative to the owner decl, the compile error1204 // Without storing source locations relative to the owner decl, the compile error
1476 // here would be off by 2 bytes (from the "7" -> "999").1205 // here would be off by 2 bytes (from the "7" -> "999").
1477 case.addError(1206 case.addError(
1478 \\export fn _start() noreturn {1207 \\pub export fn _start() noreturn {
1479 \\ const y = fibonacci(999);1208 \\ const y = fibonacci(999);
1480 \\ exit(y - 21);1209 \\ exit(y - 21);
1481 \\}1210 \\}
...@@ -1499,46 +1228,26 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1499,46 +1228,26 @@ pub fn addCases(ctx: *TestContext) !void {
1499 {1228 {
1500 var case = ctx.exe("orelse at comptime", linux_x64);1229 var case = ctx.exe("orelse at comptime", linux_x64);
1501 case.addCompareOutput(1230 case.addCompareOutput(
1502 \\export fn _start() noreturn {1231 \\pub fn main() void {
1503 \\ const i: ?u64 = 0;1232 \\ const i: ?u64 = 0;
1504 \\ const orelsed = i orelse 5;1233 \\ const result = i orelse 5;
1505 \\ assert(orelsed == 0);1234 \\ assert(result == 0);
1506 \\ exit();
1507 \\}1235 \\}
1508 \\fn assert(b: bool) void {1236 \\fn assert(b: bool) void {
1509 \\ if (!b) unreachable;1237 \\ if (!b) unreachable;
1510 \\}1238 \\}
1511 \\fn exit() noreturn {
1512 \\ asm volatile ("syscall"
1513 \\ :
1514 \\ : [number] "{rax}" (231),
1515 \\ [arg1] "{rdi}" (0)
1516 \\ : "rcx", "r11", "memory"
1517 \\ );
1518 \\ unreachable;
1519 \\}
1520 ,1239 ,
1521 "",1240 "",
1522 );1241 );
1523 case.addCompareOutput(1242 case.addCompareOutput(
1524 \\export fn _start() noreturn {1243 \\pub fn main() void {
1525 \\ const i: ?u64 = null;1244 \\ const i: ?u64 = null;
1526 \\ const orelsed = i orelse 5;1245 \\ const result = i orelse 5;
1527 \\ assert(orelsed == 5);1246 \\ assert(result == 5);
1528 \\ exit();
1529 \\}1247 \\}
1530 \\fn assert(b: bool) void {1248 \\fn assert(b: bool) void {
1531 \\ if (!b) unreachable;1249 \\ if (!b) unreachable;
1532 \\}1250 \\}
1533 \\fn exit() noreturn {
1534 \\ asm volatile ("syscall"
1535 \\ :
1536 \\ : [number] "{rax}" (231),
1537 \\ [arg1] "{rdi}" (0)
1538 \\ : "rcx", "r11", "memory"
1539 \\ );
1540 \\ unreachable;
1541 \\}
1542 ,1251 ,
1543 "",1252 "",
1544 );1253 );
...@@ -1547,7 +1256,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1547,7 +1256,7 @@ pub fn addCases(ctx: *TestContext) !void {
1547 {1256 {
1548 var case = ctx.exe("only 1 function and it gets updated", linux_x64);1257 var case = ctx.exe("only 1 function and it gets updated", linux_x64);
1549 case.addCompareOutput(1258 case.addCompareOutput(
1550 \\export fn _start() noreturn {1259 \\pub export fn _start() noreturn {
1551 \\ asm volatile ("syscall"1260 \\ asm volatile ("syscall"
1552 \\ :1261 \\ :
1553 \\ : [number] "{rax}" (60), // exit1262 \\ : [number] "{rax}" (60), // exit
...@@ -1560,7 +1269,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1560,7 +1269,7 @@ pub fn addCases(ctx: *TestContext) !void {
1560 "",1269 "",
1561 );1270 );
1562 case.addCompareOutput(1271 case.addCompareOutput(
1563 \\export fn _start() noreturn {1272 \\pub export fn _start() noreturn {
1564 \\ asm volatile ("syscall"1273 \\ asm volatile ("syscall"
1565 \\ :1274 \\ :
1566 \\ : [number] "{rax}" (231), // exit_group1275 \\ : [number] "{rax}" (231), // exit_group
...@@ -1576,20 +1285,10 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1576,20 +1285,10 @@ pub fn addCases(ctx: *TestContext) !void {
1576 {1285 {
1577 var case = ctx.exe("passing u0 to function", linux_x64);1286 var case = ctx.exe("passing u0 to function", linux_x64);
1578 case.addCompareOutput(1287 case.addCompareOutput(
1579 \\export fn _start() noreturn {1288 \\pub fn main() void {
1580 \\ doNothing(0);1289 \\ doNothing(0);
1581 \\ exit();
1582 \\}1290 \\}
1583 \\fn doNothing(arg: u0) void {}1291 \\fn doNothing(arg: u0) void {}
1584 \\fn exit() noreturn {
1585 \\ asm volatile ("syscall"
1586 \\ :
1587 \\ : [number] "{rax}" (231),
1588 \\ [arg1] "{rdi}" (0)
1589 \\ : "rcx", "r11", "memory"
1590 \\ );
1591 \\ unreachable;
1592 \\}
1593 ,1292 ,
1594 "",1293 "",
1595 );1294 );
...@@ -1597,119 +1296,67 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1597,119 +1296,67 @@ pub fn addCases(ctx: *TestContext) !void {
1597 {1296 {
1598 var case = ctx.exe("catch at comptime", linux_x64);1297 var case = ctx.exe("catch at comptime", linux_x64);
1599 case.addCompareOutput(1298 case.addCompareOutput(
1600 \\export fn _start() noreturn {1299 \\pub fn main() void {
1601 \\ const i: anyerror!u64 = 0;1300 \\ const i: anyerror!u64 = 0;
1602 \\ const caught = i catch 5;1301 \\ const caught = i catch 5;
1603 \\ assert(caught == 0);1302 \\ assert(caught == 0);
1604 \\ exit();
1605 \\}1303 \\}
1606 \\fn assert(b: bool) void {1304 \\fn assert(b: bool) void {
1607 \\ if (!b) unreachable;1305 \\ if (!b) unreachable;
1608 \\}1306 \\}
1609 \\fn exit() noreturn {
1610 \\ asm volatile ("syscall"
1611 \\ :
1612 \\ : [number] "{rax}" (231),
1613 \\ [arg1] "{rdi}" (0)
1614 \\ : "rcx", "r11", "memory"
1615 \\ );
1616 \\ unreachable;
1617 \\}
1618 ,1307 ,
1619 "",1308 "",
1620 );1309 );
16211310
1622 case.addCompareOutput(1311 case.addCompareOutput(
1623 \\export fn _start() noreturn {1312 \\pub fn main() void {
1624 \\ const i: anyerror!u64 = error.B;1313 \\ const i: anyerror!u64 = error.B;
1625 \\ const caught = i catch 5;1314 \\ const caught = i catch 5;
1626 \\ assert(caught == 5);1315 \\ assert(caught == 5);
1627 \\ exit();
1628 \\}1316 \\}
1629 \\fn assert(b: bool) void {1317 \\fn assert(b: bool) void {
1630 \\ if (!b) unreachable;1318 \\ if (!b) unreachable;
1631 \\}1319 \\}
1632 \\fn exit() noreturn {
1633 \\ asm volatile ("syscall"
1634 \\ :
1635 \\ : [number] "{rax}" (231),
1636 \\ [arg1] "{rdi}" (0)
1637 \\ : "rcx", "r11", "memory"
1638 \\ );
1639 \\ unreachable;
1640 \\}
1641 ,1320 ,
1642 "",1321 "",
1643 );1322 );
16441323
1645 case.addCompareOutput(1324 case.addCompareOutput(
1646 \\export fn _start() noreturn {1325 \\pub fn main() void {
1647 \\ const a: anyerror!comptime_int = 42;1326 \\ const a: anyerror!comptime_int = 42;
1648 \\ const b: *const comptime_int = &(a catch unreachable);1327 \\ const b: *const comptime_int = &(a catch unreachable);
1649 \\ assert(b.* == 42);1328 \\ assert(b.* == 42);
1650 \\
1651 \\ exit();
1652 \\}1329 \\}
1653 \\fn assert(b: bool) void {1330 \\fn assert(b: bool) void {
1654 \\ if (!b) unreachable; // assertion failure1331 \\ if (!b) unreachable; // assertion failure
1655 \\}1332 \\}
1656 \\fn exit() noreturn {
1657 \\ asm volatile ("syscall"
1658 \\ :
1659 \\ : [number] "{rax}" (231),
1660 \\ [arg1] "{rdi}" (0)
1661 \\ : "rcx", "r11", "memory"
1662 \\ );
1663 \\ unreachable;
1664 \\}
1665 , "");1333 , "");
16661334
1667 case.addCompareOutput(1335 case.addCompareOutput(
1668 \\export fn _start() noreturn {1336 \\pub fn main() void {
1669 \\ const a: anyerror!u32 = error.B;1337 \\ const a: anyerror!u32 = error.B;
1670 \\ _ = &(a catch |err| assert(err == error.B));1338 \\ _ = &(a catch |err| assert(err == error.B));
1671 \\ exit();
1672 \\}1339 \\}
1673 \\fn assert(b: bool) void {1340 \\fn assert(b: bool) void {
1674 \\ if (!b) unreachable;1341 \\ if (!b) unreachable;
1675 \\}1342 \\}
1676 \\fn exit() noreturn {
1677 \\ asm volatile ("syscall"
1678 \\ :
1679 \\ : [number] "{rax}" (231),
1680 \\ [arg1] "{rdi}" (0)
1681 \\ : "rcx", "r11", "memory"
1682 \\ );
1683 \\ unreachable;
1684 \\}
1685 , "");1343 , "");
16861344
1687 case.addCompareOutput(1345 case.addCompareOutput(
1688 \\export fn _start() noreturn {1346 \\pub fn main() void {
1689 \\ const a: anyerror!u32 = error.Bar;1347 \\ const a: anyerror!u32 = error.Bar;
1690 \\ a catch |err| assert(err == error.Bar);1348 \\ a catch |err| assert(err == error.Bar);
1691 \\
1692 \\ exit();
1693 \\}1349 \\}
1694 \\fn assert(b: bool) void {1350 \\fn assert(b: bool) void {
1695 \\ if (!b) unreachable;1351 \\ if (!b) unreachable;
1696 \\}1352 \\}
1697 \\fn exit() noreturn {
1698 \\ asm volatile ("syscall"
1699 \\ :
1700 \\ : [number] "{rax}" (231),
1701 \\ [arg1] "{rdi}" (0)
1702 \\ : "rcx", "r11", "memory"
1703 \\ );
1704 \\ unreachable;
1705 \\}
1706 , "");1353 , "");
1707 }1354 }
1708 {1355 {
1709 var case = ctx.exe("merge error sets", linux_x64);1356 var case = ctx.exe("merge error sets", linux_x64);
17101357
1711 case.addCompareOutput(1358 case.addCompareOutput(
1712 \\export fn _start() noreturn {1359 \\pub fn main() void {
1713 \\ const E = error{ A, B, D } || error { A, B, C };1360 \\ const E = error{ A, B, D } || error { A, B, C };
1714 \\ const a = E.A;1361 \\ const a = E.A;
1715 \\ const b = E.B;1362 \\ const b = E.B;
...@@ -1720,22 +1367,27 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1720,22 +1367,27 @@ pub fn addCases(ctx: *TestContext) !void {
1720 \\ const y = E2.Y;1367 \\ const y = E2.Y;
1721 \\ const z = E2.Z;1368 \\ const z = E2.Z;
1722 \\ assert(anyerror || error { Z } == anyerror);1369 \\ assert(anyerror || error { Z } == anyerror);
1723 \\ exit();
1724 \\}1370 \\}
1725 \\fn assert(b: bool) void {1371 \\fn assert(b: bool) void {
1726 \\ if (!b) unreachable;1372 \\ if (!b) unreachable;
1727 \\}1373 \\}
1728 \\fn exit() noreturn {1374 ,
1729 \\ asm volatile ("syscall"1375 "",
1730 \\ :1376 );
1377 }
1378 {
1379 var case = ctx.exe("inline assembly", linux_x64);
1380
1381 case.addError(
1382 \\pub fn main() void {
1383 \\ const number = 1234;
1384 \\ const x = asm volatile ("syscall"
1385 \\ : [o] "{rax}" (-> number)
1731 \\ : [number] "{rax}" (231),1386 \\ : [number] "{rax}" (231),
1732 \\ [arg1] "{rdi}" (0)1387 \\ [arg1] "{rdi}" (code)
1733 \\ : "rcx", "r11", "memory"1388 \\ : "rcx", "r11", "memory"
1734 \\ );1389 \\ );
1735 \\ unreachable;
1736 \\}1390 \\}
1737 ,1391 , &[_][]const u8{":4:27: error: expected type, found comptime_int"});
1738 "",
1739 );
1740 }1392 }
1741}1393}
test/stage2/wasm.zig+32-32
...@@ -11,7 +11,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -11,7 +11,7 @@ pub fn addCases(ctx: *TestContext) !void {
11 var case = ctx.exe("wasm function calls", wasi);11 var case = ctx.exe("wasm function calls", wasi);
1212
13 case.addCompareOutput(13 case.addCompareOutput(
14 \\export fn _start() u32 {14 \\pub export fn _start() u32 {
15 \\ foo();15 \\ foo();
16 \\ bar();16 \\ bar();
17 \\ return 42;17 \\ return 42;
...@@ -26,7 +26,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -26,7 +26,7 @@ pub fn addCases(ctx: *TestContext) !void {
26 );26 );
2727
28 case.addCompareOutput(28 case.addCompareOutput(
29 \\export fn _start() i64 {29 \\pub export fn _start() i64 {
30 \\ bar();30 \\ bar();
31 \\ foo();31 \\ foo();
32 \\ foo();32 \\ foo();
...@@ -44,7 +44,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -44,7 +44,7 @@ pub fn addCases(ctx: *TestContext) !void {
44 );44 );
4545
46 case.addCompareOutput(46 case.addCompareOutput(
47 \\export fn _start() f32 {47 \\pub export fn _start() f32 {
48 \\ bar();48 \\ bar();
49 \\ foo();49 \\ foo();
50 \\ return 42.0;50 \\ return 42.0;
...@@ -66,7 +66,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -66,7 +66,7 @@ pub fn addCases(ctx: *TestContext) !void {
66 );66 );
6767
68 case.addCompareOutput(68 case.addCompareOutput(
69 \\export fn _start() u32 {69 \\pub export fn _start() u32 {
70 \\ foo(10, 20);70 \\ foo(10, 20);
71 \\ return 5;71 \\ return 5;
72 \\}72 \\}
...@@ -78,7 +78,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -78,7 +78,7 @@ pub fn addCases(ctx: *TestContext) !void {
78 var case = ctx.exe("wasm locals", wasi);78 var case = ctx.exe("wasm locals", wasi);
7979
80 case.addCompareOutput(80 case.addCompareOutput(
81 \\export fn _start() u32 {81 \\pub export fn _start() u32 {
82 \\ var i: u32 = 5;82 \\ var i: u32 = 5;
83 \\ var y: f32 = 42.0;83 \\ var y: f32 = 42.0;
84 \\ var x: u32 = 10;84 \\ var x: u32 = 10;
...@@ -87,7 +87,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -87,7 +87,7 @@ pub fn addCases(ctx: *TestContext) !void {
87 , "5\n");87 , "5\n");
8888
89 case.addCompareOutput(89 case.addCompareOutput(
90 \\export fn _start() u32 {90 \\pub export fn _start() u32 {
91 \\ var i: u32 = 5;91 \\ var i: u32 = 5;
92 \\ var y: f32 = 42.0;92 \\ var y: f32 = 42.0;
93 \\ var x: u32 = 10;93 \\ var x: u32 = 10;
...@@ -106,7 +106,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -106,7 +106,7 @@ pub fn addCases(ctx: *TestContext) !void {
106 var case = ctx.exe("wasm binary operands", wasi);106 var case = ctx.exe("wasm binary operands", wasi);
107107
108 case.addCompareOutput(108 case.addCompareOutput(
109 \\export fn _start() u32 {109 \\pub export fn _start() u32 {
110 \\ var i: u32 = 5;110 \\ var i: u32 = 5;
111 \\ i += 20;111 \\ i += 20;
112 \\ return i;112 \\ return i;
...@@ -114,7 +114,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -114,7 +114,7 @@ pub fn addCases(ctx: *TestContext) !void {
114 , "25\n");114 , "25\n");
115115
116 case.addCompareOutput(116 case.addCompareOutput(
117 \\export fn _start() u32 {117 \\pub export fn _start() u32 {
118 \\ var i: u32 = 5;118 \\ var i: u32 = 5;
119 \\ i += 20;119 \\ i += 20;
120 \\ var result: u32 = foo(i, 10);120 \\ var result: u32 = foo(i, 10);
...@@ -126,7 +126,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -126,7 +126,7 @@ pub fn addCases(ctx: *TestContext) !void {
126 , "35\n");126 , "35\n");
127127
128 case.addCompareOutput(128 case.addCompareOutput(
129 \\export fn _start() u32 {129 \\pub export fn _start() u32 {
130 \\ var i: u32 = 20;130 \\ var i: u32 = 20;
131 \\ i -= 5;131 \\ i -= 5;
132 \\ return i;132 \\ return i;
...@@ -134,7 +134,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -134,7 +134,7 @@ pub fn addCases(ctx: *TestContext) !void {
134 , "15\n");134 , "15\n");
135135
136 case.addCompareOutput(136 case.addCompareOutput(
137 \\export fn _start() u32 {137 \\pub export fn _start() u32 {
138 \\ var i: u32 = 5;138 \\ var i: u32 = 5;
139 \\ i -= 3;139 \\ i -= 3;
140 \\ var result: u32 = foo(i, 10);140 \\ var result: u32 = foo(i, 10);
...@@ -146,7 +146,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -146,7 +146,7 @@ pub fn addCases(ctx: *TestContext) !void {
146 , "8\n");146 , "8\n");
147147
148 case.addCompareOutput(148 case.addCompareOutput(
149 \\export fn _start() u32 {149 \\pub export fn _start() u32 {
150 \\ var i: u32 = 5;150 \\ var i: u32 = 5;
151 \\ i *= 7;151 \\ i *= 7;
152 \\ var result: u32 = foo(i, 10);152 \\ var result: u32 = foo(i, 10);
...@@ -158,7 +158,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -158,7 +158,7 @@ pub fn addCases(ctx: *TestContext) !void {
158 , "350\n");158 , "350\n");
159159
160 case.addCompareOutput(160 case.addCompareOutput(
161 \\export fn _start() u32 {161 \\pub export fn _start() u32 {
162 \\ var i: u32 = 352;162 \\ var i: u32 = 352;
163 \\ i /= 7; // i = 50163 \\ i /= 7; // i = 50
164 \\ var result: u32 = foo(i, 7);164 \\ var result: u32 = foo(i, 7);
...@@ -170,7 +170,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -170,7 +170,7 @@ pub fn addCases(ctx: *TestContext) !void {
170 , "7\n");170 , "7\n");
171171
172 case.addCompareOutput(172 case.addCompareOutput(
173 \\export fn _start() u32 {173 \\pub export fn _start() u32 {
174 \\ var i: u32 = 5;174 \\ var i: u32 = 5;
175 \\ i &= 6;175 \\ i &= 6;
176 \\ return i;176 \\ return i;
...@@ -178,7 +178,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -178,7 +178,7 @@ pub fn addCases(ctx: *TestContext) !void {
178 , "4\n");178 , "4\n");
179179
180 case.addCompareOutput(180 case.addCompareOutput(
181 \\export fn _start() u32 {181 \\pub export fn _start() u32 {
182 \\ var i: u32 = 5;182 \\ var i: u32 = 5;
183 \\ i |= 6;183 \\ i |= 6;
184 \\ return i;184 \\ return i;
...@@ -186,7 +186,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -186,7 +186,7 @@ pub fn addCases(ctx: *TestContext) !void {
186 , "7\n");186 , "7\n");
187187
188 case.addCompareOutput(188 case.addCompareOutput(
189 \\export fn _start() u32 {189 \\pub export fn _start() u32 {
190 \\ var i: u32 = 5;190 \\ var i: u32 = 5;
191 \\ i ^= 6;191 \\ i ^= 6;
192 \\ return i;192 \\ return i;
...@@ -194,7 +194,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -194,7 +194,7 @@ pub fn addCases(ctx: *TestContext) !void {
194 , "3\n");194 , "3\n");
195195
196 case.addCompareOutput(196 case.addCompareOutput(
197 \\export fn _start() bool {197 \\pub export fn _start() bool {
198 \\ var b: bool = false;198 \\ var b: bool = false;
199 \\ b = b or false;199 \\ b = b or false;
200 \\ return b;200 \\ return b;
...@@ -202,7 +202,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -202,7 +202,7 @@ pub fn addCases(ctx: *TestContext) !void {
202 , "0\n");202 , "0\n");
203203
204 case.addCompareOutput(204 case.addCompareOutput(
205 \\export fn _start() bool {205 \\pub export fn _start() bool {
206 \\ var b: bool = true;206 \\ var b: bool = true;
207 \\ b = b or false;207 \\ b = b or false;
208 \\ return b;208 \\ return b;
...@@ -210,7 +210,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -210,7 +210,7 @@ pub fn addCases(ctx: *TestContext) !void {
210 , "1\n");210 , "1\n");
211211
212 case.addCompareOutput(212 case.addCompareOutput(
213 \\export fn _start() bool {213 \\pub export fn _start() bool {
214 \\ var b: bool = false;214 \\ var b: bool = false;
215 \\ b = b or true;215 \\ b = b or true;
216 \\ return b;216 \\ return b;
...@@ -218,7 +218,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -218,7 +218,7 @@ pub fn addCases(ctx: *TestContext) !void {
218 , "1\n");218 , "1\n");
219219
220 case.addCompareOutput(220 case.addCompareOutput(
221 \\export fn _start() bool {221 \\pub export fn _start() bool {
222 \\ var b: bool = true;222 \\ var b: bool = true;
223 \\ b = b or true;223 \\ b = b or true;
224 \\ return b;224 \\ return b;
...@@ -226,7 +226,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -226,7 +226,7 @@ pub fn addCases(ctx: *TestContext) !void {
226 , "1\n");226 , "1\n");
227227
228 case.addCompareOutput(228 case.addCompareOutput(
229 \\export fn _start() bool {229 \\pub export fn _start() bool {
230 \\ var b: bool = false;230 \\ var b: bool = false;
231 \\ b = b and false;231 \\ b = b and false;
232 \\ return b;232 \\ return b;
...@@ -234,7 +234,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -234,7 +234,7 @@ pub fn addCases(ctx: *TestContext) !void {
234 , "0\n");234 , "0\n");
235235
236 case.addCompareOutput(236 case.addCompareOutput(
237 \\export fn _start() bool {237 \\pub export fn _start() bool {
238 \\ var b: bool = true;238 \\ var b: bool = true;
239 \\ b = b and false;239 \\ b = b and false;
240 \\ return b;240 \\ return b;
...@@ -242,7 +242,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -242,7 +242,7 @@ pub fn addCases(ctx: *TestContext) !void {
242 , "0\n");242 , "0\n");
243243
244 case.addCompareOutput(244 case.addCompareOutput(
245 \\export fn _start() bool {245 \\pub export fn _start() bool {
246 \\ var b: bool = false;246 \\ var b: bool = false;
247 \\ b = b and true;247 \\ b = b and true;
248 \\ return b;248 \\ return b;
...@@ -250,7 +250,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -250,7 +250,7 @@ pub fn addCases(ctx: *TestContext) !void {
250 , "0\n");250 , "0\n");
251251
252 case.addCompareOutput(252 case.addCompareOutput(
253 \\export fn _start() bool {253 \\pub export fn _start() bool {
254 \\ var b: bool = true;254 \\ var b: bool = true;
255 \\ b = b and true;255 \\ b = b and true;
256 \\ return b;256 \\ return b;
...@@ -262,7 +262,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -262,7 +262,7 @@ pub fn addCases(ctx: *TestContext) !void {
262 var case = ctx.exe("wasm conditions", wasi);262 var case = ctx.exe("wasm conditions", wasi);
263263
264 case.addCompareOutput(264 case.addCompareOutput(
265 \\export fn _start() u32 {265 \\pub export fn _start() u32 {
266 \\ var i: u32 = 5;266 \\ var i: u32 = 5;
267 \\ if (i > @as(u32, 4)) {267 \\ if (i > @as(u32, 4)) {
268 \\ i += 10;268 \\ i += 10;
...@@ -272,7 +272,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -272,7 +272,7 @@ pub fn addCases(ctx: *TestContext) !void {
272 , "15\n");272 , "15\n");
273273
274 case.addCompareOutput(274 case.addCompareOutput(
275 \\export fn _start() u32 {275 \\pub export fn _start() u32 {
276 \\ var i: u32 = 5;276 \\ var i: u32 = 5;
277 \\ if (i < @as(u32, 4)) {277 \\ if (i < @as(u32, 4)) {
278 \\ i += 10;278 \\ i += 10;
...@@ -284,7 +284,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -284,7 +284,7 @@ pub fn addCases(ctx: *TestContext) !void {
284 , "2\n");284 , "2\n");
285285
286 case.addCompareOutput(286 case.addCompareOutput(
287 \\export fn _start() u32 {287 \\pub export fn _start() u32 {
288 \\ var i: u32 = 5;288 \\ var i: u32 = 5;
289 \\ if (i < @as(u32, 4)) {289 \\ if (i < @as(u32, 4)) {
290 \\ i += 10;290 \\ i += 10;
...@@ -296,7 +296,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -296,7 +296,7 @@ pub fn addCases(ctx: *TestContext) !void {
296 , "20\n");296 , "20\n");
297297
298 case.addCompareOutput(298 case.addCompareOutput(
299 \\export fn _start() u32 {299 \\pub export fn _start() u32 {
300 \\ var i: u32 = 11;300 \\ var i: u32 = 11;
301 \\ if (i < @as(u32, 4)) {301 \\ if (i < @as(u32, 4)) {
302 \\ i += 10;302 \\ i += 10;
...@@ -312,7 +312,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -312,7 +312,7 @@ pub fn addCases(ctx: *TestContext) !void {
312 , "31\n");312 , "31\n");
313313
314 case.addCompareOutput(314 case.addCompareOutput(
315 \\export fn _start() void {315 \\pub export fn _start() void {
316 \\ assert(foo(true) != @as(i32, 30));316 \\ assert(foo(true) != @as(i32, 30));
317 \\}317 \\}
318 \\318 \\
...@@ -327,7 +327,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -327,7 +327,7 @@ pub fn addCases(ctx: *TestContext) !void {
327 , "");327 , "");
328328
329 case.addCompareOutput(329 case.addCompareOutput(
330 \\export fn _start() void {330 \\pub export fn _start() void {
331 \\ assert(foo(false) == @as(i32, 20));331 \\ assert(foo(false) == @as(i32, 20));
332 \\ assert(foo(true) == @as(i32, 30));332 \\ assert(foo(true) == @as(i32, 30));
333 \\}333 \\}
...@@ -351,7 +351,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -351,7 +351,7 @@ pub fn addCases(ctx: *TestContext) !void {
351 var case = ctx.exe("wasm while loops", wasi);351 var case = ctx.exe("wasm while loops", wasi);
352352
353 case.addCompareOutput(353 case.addCompareOutput(
354 \\export fn _start() u32 {354 \\pub export fn _start() u32 {
355 \\ var i: u32 = 0;355 \\ var i: u32 = 0;
356 \\ while(i < @as(u32, 5)){356 \\ while(i < @as(u32, 5)){
357 \\ i += 1;357 \\ i += 1;
...@@ -362,7 +362,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -362,7 +362,7 @@ pub fn addCases(ctx: *TestContext) !void {
362 , "5\n");362 , "5\n");
363363
364 case.addCompareOutput(364 case.addCompareOutput(
365 \\export fn _start() u32 {365 \\pub export fn _start() u32 {
366 \\ var i: u32 = 0;366 \\ var i: u32 = 0;
367 \\ while(i < @as(u32, 10)){367 \\ while(i < @as(u32, 10)){
368 \\ var x: u32 = 1;368 \\ var x: u32 = 1;
...@@ -373,7 +373,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -373,7 +373,7 @@ pub fn addCases(ctx: *TestContext) !void {
373 , "10\n");373 , "10\n");
374374
375 case.addCompareOutput(375 case.addCompareOutput(
376 \\export fn _start() u32 {376 \\pub export fn _start() u32 {
377 \\ var i: u32 = 0;377 \\ var i: u32 = 0;
378 \\ while(i < @as(u32, 10)){378 \\ while(i < @as(u32, 10)){
379 \\ var x: u32 = 1;379 \\ var x: u32 = 1;
test/standalone/issue_339/test.zig+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1const StackTrace = @import("builtin").StackTrace;1const StackTrace = @import("std").builtin.StackTrace;
2pub fn panic(msg: []const u8, stack_trace: ?*StackTrace) noreturn {2pub fn panic(msg: []const u8, stack_trace: ?*StackTrace) noreturn {
3 @breakpoint();3 @breakpoint();
4 while (true) {}4 while (true) {}
test/tests.zig+5-5
...@@ -523,7 +523,7 @@ pub fn addPkgTests(...@@ -523,7 +523,7 @@ pub fn addPkgTests(
523 if (skip_single_threaded and test_target.single_threaded)523 if (skip_single_threaded and test_target.single_threaded)
524 continue;524 continue;
525525
526 const ArchTag = std.meta.Tag(builtin.Arch);526 const ArchTag = std.meta.Tag(std.Target.Cpu.Arch);
527 if (test_target.disable_native and527 if (test_target.disable_native and
528 test_target.target.getOsTag() == std.Target.current.os.tag and528 test_target.target.getOsTag() == std.Target.current.os.tag and
529 test_target.target.getCpuArch() == std.Target.current.cpu.arch)529 test_target.target.getCpuArch() == std.Target.current.cpu.arch)
...@@ -588,11 +588,11 @@ pub const StackTracesContext = struct {...@@ -588,11 +588,11 @@ pub const StackTracesContext = struct {
588 if (config.exclude.exclude()) return;588 if (config.exclude.exclude()) return;
589 }589 }
590 if (@hasField(@TypeOf(config), "exclude_arch")) {590 if (@hasField(@TypeOf(config), "exclude_arch")) {
591 const exclude_arch: []const builtin.Cpu.Arch = &config.exclude_arch;591 const exclude_arch: []const std.Target.Cpu.Arch = &config.exclude_arch;
592 for (exclude_arch) |arch| if (arch == builtin.cpu.arch) return;592 for (exclude_arch) |arch| if (arch == builtin.cpu.arch) return;
593 }593 }
594 if (@hasField(@TypeOf(config), "exclude_os")) {594 if (@hasField(@TypeOf(config), "exclude_os")) {
595 const exclude_os: []const builtin.Os.Tag = &config.exclude_os;595 const exclude_os: []const std.Target.Os.Tag = &config.exclude_os;
596 for (exclude_os) |os| if (os == builtin.os.tag) return;596 for (exclude_os) |os| if (os == builtin.os.tag) return;
597 }597 }
598 for (self.modes) |mode| {598 for (self.modes) |mode| {
...@@ -632,11 +632,11 @@ pub const StackTracesContext = struct {...@@ -632,11 +632,11 @@ pub const StackTracesContext = struct {
632 if (mode_config.exclude.exclude()) return;632 if (mode_config.exclude.exclude()) return;
633 }633 }
634 if (@hasField(@TypeOf(mode_config), "exclude_arch")) {634 if (@hasField(@TypeOf(mode_config), "exclude_arch")) {
635 const exclude_arch: []const builtin.Cpu.Arch = &mode_config.exclude_arch;635 const exclude_arch: []const std.Target.Cpu.Arch = &mode_config.exclude_arch;
636 for (exclude_arch) |arch| if (arch == builtin.cpu.arch) return;636 for (exclude_arch) |arch| if (arch == builtin.cpu.arch) return;
637 }637 }
638 if (@hasField(@TypeOf(mode_config), "exclude_os")) {638 if (@hasField(@TypeOf(mode_config), "exclude_os")) {
639 const exclude_os: []const builtin.Os.Tag = &mode_config.exclude_os;639 const exclude_os: []const std.Target.Os.Tag = &mode_config.exclude_os;
640 for (exclude_os) |os| if (os == builtin.os.tag) return;640 for (exclude_os) |os| if (os == builtin.os.tag) return;
641 }641 }
642642
tools/gen_spirv_spec.zig+1-1
...@@ -26,7 +26,7 @@ fn render(writer: anytype, registry: g.Registry) !void {...@@ -26,7 +26,7 @@ fn render(writer: anytype, registry: g.Registry) !void {
26 try writer.writeAll(26 try writer.writeAll(
27 \\//! This file is auto-generated by tools/gen_spirv_spec.zig.27 \\//! This file is auto-generated by tools/gen_spirv_spec.zig.
28 \\28 \\
29 \\const Version = @import("builtin").Version;29 \\const Version = @import("std").builtin.Version;
30 \\30 \\
31 );31 );
3232