authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-31 15:55:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-31 15:55:44-07:00
logd46446e4dfade96fe0db773ce4d8d1b7154cae92
treeb0cb2fbc5ba6cf2d800c3a3f96cd760863b63aca
parentd3389eadf42417deae2d9ba01f9529be861fb998
parentff125db53d8c18a63872ebdcdf6dd9653eb3f56b

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


101 files changed, 3300 insertions(+), 2139 deletions(-)

CMakeLists.txt+1-1
......@@ -670,7 +670,7 @@ set(ZIG_STAGE2_SOURCES
670670 "${CMAKE_SOURCE_DIR}/lib/std/target/powerpc.zig"
671671 "${CMAKE_SOURCE_DIR}/lib/std/target/riscv.zig"
672672 "${CMAKE_SOURCE_DIR}/lib/std/target/sparc.zig"
673 "${CMAKE_SOURCE_DIR}/lib/std/target/systemz.zig"
673 "${CMAKE_SOURCE_DIR}/lib/std/target/s390x.zig"
674674 "${CMAKE_SOURCE_DIR}/lib/std/target/wasm.zig"
675675 "${CMAKE_SOURCE_DIR}/lib/std/target/x86.zig"
676676 "${CMAKE_SOURCE_DIR}/lib/std/Thread.zig"
build.zig+65-31
......@@ -238,7 +238,15 @@ pub fn build(b: *Builder) !void {
238238 exe_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version));
239239
240240 if (enable_llvm) {
241 const cmake_cfg = if (static_llvm) null else findAndParseConfigH(b, config_h_path_option);
241 const cmake_cfg = if (static_llvm) null else blk: {
242 if (findConfigH(b, config_h_path_option)) |config_h_path| {
243 const file_contents = fs.cwd().readFileAlloc(b.allocator, config_h_path, max_config_h_bytes) catch unreachable;
244 break :blk parseConfigH(b, file_contents);
245 } else {
246 std.log.warn("config.h could not be located automatically. Consider providing it explicitly via \"-Dconfig_h\"", .{});
247 break :blk null;
248 }
249 };
242250
243251 if (is_stage1) {
244252 const softfloat = b.addStaticLibrary("softfloat", null);
......@@ -565,13 +573,17 @@ fn addCmakeCfgOptionsToExe(
565573 exe.linkLibCpp();
566574 } else {
567575 const need_cpp_includes = true;
576 const lib_suffix = switch (cfg.llvm_linkage) {
577 .static => exe.target.staticLibSuffix()[1..],
578 .dynamic => exe.target.dynamicLibSuffix()[1..],
579 };
568580
569581 // System -lc++ must be used because in this code path we are attempting to link
570582 // against system-provided LLVM, Clang, LLD.
571583 if (exe.target.getOsTag() == .linux) {
572 // First we try to static link against gcc libstdc++. If that doesn't work,
573 // we fall back to -lc++ and cross our fingers.
574 addCxxKnownPath(b, cfg, exe, "libstdc++.a", "", need_cpp_includes) catch |err| switch (err) {
584 // First we try to link against gcc libstdc++. If that doesn't work, we fall
585 // back to -lc++ and cross our fingers.
586 addCxxKnownPath(b, cfg, exe, b.fmt("libstdc++.{s}", .{lib_suffix}), "", need_cpp_includes) catch |err| switch (err) {
575587 error.RequiredLibraryNotFound => {
576588 exe.linkSystemLibrary("c++");
577589 },
......@@ -579,11 +591,11 @@ fn addCmakeCfgOptionsToExe(
579591 };
580592 exe.linkSystemLibrary("unwind");
581593 } else if (exe.target.isFreeBSD()) {
582 try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes);
594 try addCxxKnownPath(b, cfg, exe, b.fmt("libc++.{s}", .{lib_suffix}), null, need_cpp_includes);
583595 exe.linkSystemLibrary("pthread");
584596 } else if (exe.target.getOsTag() == .openbsd) {
585 try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes);
586 try addCxxKnownPath(b, cfg, exe, "libc++abi.a", null, need_cpp_includes);
597 try addCxxKnownPath(b, cfg, exe, b.fmt("libc++.{s}", .{lib_suffix}), null, need_cpp_includes);
598 try addCxxKnownPath(b, cfg, exe, b.fmt("libc++abi.{s}", .{lib_suffix}), null, need_cpp_includes);
587599 } else if (exe.target.isDarwin()) {
588600 exe.linkSystemLibrary("c++");
589601 }
......@@ -689,31 +701,53 @@ const CMakeConfig = struct {
689701
690702const max_config_h_bytes = 1 * 1024 * 1024;
691703
692fn findAndParseConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?CMakeConfig {
693 const config_h_text: []const u8 = if (config_h_path_option) |config_h_path| blk: {
694 break :blk fs.cwd().readFileAlloc(b.allocator, config_h_path, max_config_h_bytes) catch unreachable;
695 } else blk: {
696 // TODO this should stop looking for config.h once it detects we hit the
697 // zig source root directory.
698 var check_dir = fs.path.dirname(b.zig_exe).?;
699 while (true) {
700 var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable;
701 defer dir.close();
702
703 break :blk dir.readFileAlloc(b.allocator, "config.h", max_config_h_bytes) catch |err| switch (err) {
704 error.FileNotFound => {
705 const new_check_dir = fs.path.dirname(check_dir);
706 if (new_check_dir == null or mem.eql(u8, new_check_dir.?, check_dir)) {
707 return null;
708 }
709 check_dir = new_check_dir.?;
710 continue;
711 },
712 else => unreachable,
713 };
714 } else unreachable; // TODO should not need `else unreachable`.
715 };
704fn findConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?[]const u8 {
705 if (config_h_path_option) |path| {
706 var config_h_or_err = fs.cwd().openFile(path, .{});
707 if (config_h_or_err) |*file| {
708 file.close();
709 return path;
710 } else |_| {
711 std.log.err("Could not open provided config.h: \"{s}\"", .{path});
712 std.os.exit(1);
713 }
714 }
715
716 var check_dir = fs.path.dirname(b.zig_exe).?;
717 while (true) {
718 var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable;
719 defer dir.close();
720
721 // Check if config.h is present in dir
722 var config_h_or_err = dir.openFile("config.h", .{});
723 if (config_h_or_err) |*file| {
724 file.close();
725 return fs.path.join(
726 b.allocator,
727 &[_][]const u8{ check_dir, "config.h" },
728 ) catch unreachable;
729 } else |e| switch (e) {
730 error.FileNotFound => {},
731 else => unreachable,
732 }
733
734 // Check if we reached the source root by looking for .git, and bail if so
735 var git_dir_or_err = dir.openDir(".git", .{});
736 if (git_dir_or_err) |*git_dir| {
737 git_dir.close();
738 return null;
739 } else |_| {}
740
741 // Otherwise, continue search in the parent directory
742 const new_check_dir = fs.path.dirname(check_dir);
743 if (new_check_dir == null or mem.eql(u8, new_check_dir.?, check_dir)) {
744 return null;
745 }
746 check_dir = new_check_dir.?;
747 } else unreachable; // TODO should not need `else unreachable`.
748}
716749
750fn parseConfigH(b: *Builder, config_h_text: []const u8) ?CMakeConfig {
717751 var ctx: CMakeConfig = .{
718752 .llvm_linkage = undefined,
719753 .cmake_binary_dir = undefined,
ci/zinc/linux_test.sh+1-2
......@@ -63,8 +63,7 @@ stage3/bin/zig build test-translate-c -fqemu -fwasmtime -Denable-llvm
6363stage3/bin/zig build test-run-translated-c -fqemu -fwasmtime -Denable-llvm
6464stage3/bin/zig build test-standalone -fqemu -fwasmtime -Denable-llvm
6565stage3/bin/zig build test-cli -fqemu -fwasmtime -Denable-llvm
66# https://github.com/ziglang/zig/issues/12144
67stage3/bin/zig build test-cases -fqemu -fwasmtime
66stage3/bin/zig build test-cases -fqemu -fwasmtime -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
6867stage3/bin/zig build test-link -fqemu -fwasmtime -Denable-llvm
6968
7069$STAGE1_ZIG build test-stack-traces -fqemu -fwasmtime
cmake/Findllvm.cmake+7-5
......@@ -10,6 +10,7 @@
1010
1111
1212if(ZIG_USE_LLVM_CONFIG)
13 set(LLVM_CONFIG_ERROR_MESSAGES "")
1314 while(1)
1415 unset(LLVM_CONFIG_EXE CACHE)
1516 find_program(LLVM_CONFIG_EXE
......@@ -21,7 +22,8 @@ if(ZIG_USE_LLVM_CONFIG)
2122 "C:/Libraries/llvm-15.0.0/bin")
2223
2324 if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND")
24 if (DEFINED LLVM_CONFIG_ERROR_MESSAGE)
25 if (NOT LLVM_CONFIG_ERROR_MESSAGES STREQUAL "")
26 list(JOIN LLVM_CONFIG_ERROR_MESSAGES "\n" LLVM_CONFIG_ERROR_MESSAGE)
2527 message(FATAL_ERROR ${LLVM_CONFIG_ERROR_MESSAGE})
2628 else()
2729 message(FATAL_ERROR "unable to find llvm-config")
......@@ -37,7 +39,7 @@ if(ZIG_USE_LLVM_CONFIG)
3739 get_filename_component(LLVM_CONFIG_DIR "${LLVM_CONFIG_EXE}" DIRECTORY)
3840 if("${LLVM_CONFIG_VERSION}" VERSION_LESS 15 OR "${LLVM_CONFIG_VERSION}" VERSION_EQUAL 16 OR "${LLVM_CONFIG_VERSION}" VERSION_GREATER 16)
3941 # Save the error message, in case this is the last llvm-config we find
40 set(LLVM_CONFIG_ERROR_MESSAGE "expected LLVM 15.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
42 list(APPEND LLVM_CONFIG_ERROR_MESSAGES "expected LLVM 15.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
4143
4244 # Ignore this directory and try the search again
4345 list(APPEND CMAKE_IGNORE_PATH "${LLVM_CONFIG_DIR}")
......@@ -61,9 +63,9 @@ if(ZIG_USE_LLVM_CONFIG)
6163 if (LLVM_CONFIG_ERROR)
6264 # Save the error message, in case this is the last llvm-config we find
6365 if (ZIG_SHARED_LLVM)
64 set(LLVM_CONFIG_ERROR_MESSAGE "LLVM 15.x found at ${LLVM_CONFIG_EXE} does not support linking as a shared library")
66 list(APPEND LLVM_CONFIG_ERROR_MESSAGES "LLVM 15.x found at ${LLVM_CONFIG_EXE} does not support linking as a shared library")
6567 else()
66 set(LLVM_CONFIG_ERROR_MESSAGE "LLVM 15.x found at ${LLVM_CONFIG_EXE} does not support linking as a static library")
68 list(APPEND LLVM_CONFIG_ERROR_MESSAGES "LLVM 15.x found at ${LLVM_CONFIG_EXE} does not support linking as a static library")
6769 endif()
6870
6971 # Ignore this directory and try the search again
......@@ -81,7 +83,7 @@ if(ZIG_USE_LLVM_CONFIG)
8183 list (FIND LLVM_TARGETS_BUILT "${TARGET_NAME}" _index)
8284 if (${_index} EQUAL -1)
8385 # Save the error message, in case this is the last llvm-config we find
84 set(LLVM_CONFIG_ERROR_MESSAGE "LLVM (according to ${LLVM_CONFIG_EXE}) is missing target ${TARGET_NAME}. Zig requires LLVM to be built with all default targets enabled.")
86 list(APPEND LLVM_CONFIG_ERROR_MESSAGES "LLVM (according to ${LLVM_CONFIG_EXE}) is missing target ${TARGET_NAME}. Zig requires LLVM to be built with all default targets enabled.")
8587
8688 # Ignore this directory and try the search again
8789 list(APPEND CMAKE_IGNORE_PATH "${LLVM_CONFIG_DIR}")
lib/std/debug.zig+2
......@@ -1784,6 +1784,7 @@ pub fn updateSegfaultHandler(act: ?*const os.Sigaction) error{OperationNotSuppor
17841784 try os.sigaction(os.SIG.SEGV, act, null);
17851785 try os.sigaction(os.SIG.ILL, act, null);
17861786 try os.sigaction(os.SIG.BUS, act, null);
1787 try os.sigaction(os.SIG.FPE, act, null);
17871788}
17881789
17891790/// Attaches a global SIGSEGV handler which calls @panic("segmentation fault");
......@@ -1845,6 +1846,7 @@ fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
18451846 os.SIG.SEGV => stderr.print("Segmentation fault at address 0x{x}\n", .{addr}),
18461847 os.SIG.ILL => stderr.print("Illegal instruction at address 0x{x}\n", .{addr}),
18471848 os.SIG.BUS => stderr.print("Bus error at address 0x{x}\n", .{addr}),
1849 os.SIG.FPE => stderr.print("Arithmetic exception at address 0x{x}\n", .{addr}),
18481850 else => unreachable,
18491851 } catch os.abort();
18501852 }
lib/std/os.zig+2
......@@ -4244,6 +4244,7 @@ pub const INotifyAddWatchError = error{
42444244 SystemResources,
42454245 UserResourceLimitReached,
42464246 NotDir,
4247 WatchAlreadyExists,
42474248} || UnexpectedError;
42484249
42494250/// add a watch to an initialized inotify instance
......@@ -4266,6 +4267,7 @@ pub fn inotify_add_watchZ(inotify_fd: i32, pathname: [*:0]const u8, mask: u32) I
42664267 .NOMEM => return error.SystemResources,
42674268 .NOSPC => return error.UserResourceLimitReached,
42684269 .NOTDIR => return error.NotDir,
4270 .EXIST => return error.WatchAlreadyExists,
42694271 else => |err| return unexpectedErrno(err),
42704272 }
42714273}
lib/std/os/linux.zig+1
......@@ -2976,6 +2976,7 @@ pub const IN = struct {
29762976 pub const ONLYDIR = 0x01000000;
29772977 pub const DONT_FOLLOW = 0x02000000;
29782978 pub const EXCL_UNLINK = 0x04000000;
2979 pub const MASK_CREATE = 0x10000000;
29792980 pub const MASK_ADD = 0x20000000;
29802981
29812982 pub const ISDIR = 0x40000000;
lib/std/target.zig+5-5
......@@ -453,7 +453,7 @@ pub const Target = struct {
453453 pub const riscv = @import("target/riscv.zig");
454454 pub const sparc = @import("target/sparc.zig");
455455 pub const spirv = @import("target/spirv.zig");
456 pub const systemz = @import("target/systemz.zig");
456 pub const s390x = @import("target/s390x.zig");
457457 pub const ve = @import("target/ve.zig");
458458 pub const wasm = @import("target/wasm.zig");
459459 pub const x86 = @import("target/x86.zig");
......@@ -1178,7 +1178,7 @@ pub const Target = struct {
11781178 .amdgcn => "amdgpu",
11791179 .riscv32, .riscv64 => "riscv",
11801180 .sparc, .sparc64, .sparcel => "sparc",
1181 .s390x => "systemz",
1181 .s390x => "s390x",
11821182 .i386, .x86_64 => "x86",
11831183 .nvptx, .nvptx64 => "nvptx",
11841184 .wasm32, .wasm64 => "wasm",
......@@ -1202,7 +1202,7 @@ pub const Target = struct {
12021202 .riscv32, .riscv64 => &riscv.all_features,
12031203 .sparc, .sparc64, .sparcel => &sparc.all_features,
12041204 .spirv32, .spirv64 => &spirv.all_features,
1205 .s390x => &systemz.all_features,
1205 .s390x => &s390x.all_features,
12061206 .i386, .x86_64 => &x86.all_features,
12071207 .nvptx, .nvptx64 => &nvptx.all_features,
12081208 .ve => &ve.all_features,
......@@ -1226,7 +1226,7 @@ pub const Target = struct {
12261226 .amdgcn => comptime allCpusFromDecls(amdgpu.cpu),
12271227 .riscv32, .riscv64 => comptime allCpusFromDecls(riscv.cpu),
12281228 .sparc, .sparc64, .sparcel => comptime allCpusFromDecls(sparc.cpu),
1229 .s390x => comptime allCpusFromDecls(systemz.cpu),
1229 .s390x => comptime allCpusFromDecls(s390x.cpu),
12301230 .i386, .x86_64 => comptime allCpusFromDecls(x86.cpu),
12311231 .nvptx, .nvptx64 => comptime allCpusFromDecls(nvptx.cpu),
12321232 .ve => comptime allCpusFromDecls(ve.cpu),
......@@ -1287,7 +1287,7 @@ pub const Target = struct {
12871287 .riscv64 => &riscv.cpu.generic_rv64,
12881288 .sparc, .sparcel => &sparc.cpu.generic,
12891289 .sparc64 => &sparc.cpu.v9, // 64-bit SPARC needs v9 as the baseline
1290 .s390x => &systemz.cpu.generic,
1290 .s390x => &s390x.cpu.generic,
12911291 .i386 => &x86.cpu.i386,
12921292 .x86_64 => &x86.cpu.x86_64,
12931293 .nvptx, .nvptx64 => &nvptx.cpu.sm_20,
lib/std/target/s390x.zig created+621
......@@ -0,0 +1,621 @@
1//! This file is auto-generated by tools/update_cpu_features.zig.
2
3const std = @import("../std.zig");
4const CpuFeature = std.Target.Cpu.Feature;
5const CpuModel = std.Target.Cpu.Model;
6
7pub const Feature = enum {
8 bear_enhancement,
9 deflate_conversion,
10 dfp_packed_conversion,
11 dfp_zoned_conversion,
12 distinct_ops,
13 enhanced_dat_2,
14 enhanced_sort,
15 execution_hint,
16 fast_serialization,
17 fp_extension,
18 guarded_storage,
19 high_word,
20 insert_reference_bits_multiple,
21 interlocked_access1,
22 load_and_trap,
23 load_and_zero_rightmost_byte,
24 load_store_on_cond,
25 load_store_on_cond_2,
26 message_security_assist_extension3,
27 message_security_assist_extension4,
28 message_security_assist_extension5,
29 message_security_assist_extension7,
30 message_security_assist_extension8,
31 message_security_assist_extension9,
32 miscellaneous_extensions,
33 miscellaneous_extensions_2,
34 miscellaneous_extensions_3,
35 nnp_assist,
36 population_count,
37 processor_activity_instrumentation,
38 processor_assist,
39 reset_dat_protection,
40 reset_reference_bits_multiple,
41 soft_float,
42 transactional_execution,
43 vector,
44 vector_enhancements_1,
45 vector_enhancements_2,
46 vector_packed_decimal,
47 vector_packed_decimal_enhancement,
48 vector_packed_decimal_enhancement_2,
49};
50
51pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet;
52pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas;
53pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny;
54pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll;
55
56pub const all_features = blk: {
57 const len = @typeInfo(Feature).Enum.fields.len;
58 std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
59 var result: [len]CpuFeature = undefined;
60 result[@enumToInt(Feature.bear_enhancement)] = .{
61 .llvm_name = "bear-enhancement",
62 .description = "Assume that the BEAR-enhancement facility is installed",
63 .dependencies = featureSet(&[_]Feature{}),
64 };
65 result[@enumToInt(Feature.deflate_conversion)] = .{
66 .llvm_name = "deflate-conversion",
67 .description = "Assume that the deflate-conversion facility is installed",
68 .dependencies = featureSet(&[_]Feature{}),
69 };
70 result[@enumToInt(Feature.dfp_packed_conversion)] = .{
71 .llvm_name = "dfp-packed-conversion",
72 .description = "Assume that the DFP packed-conversion facility is installed",
73 .dependencies = featureSet(&[_]Feature{}),
74 };
75 result[@enumToInt(Feature.dfp_zoned_conversion)] = .{
76 .llvm_name = "dfp-zoned-conversion",
77 .description = "Assume that the DFP zoned-conversion facility is installed",
78 .dependencies = featureSet(&[_]Feature{}),
79 };
80 result[@enumToInt(Feature.distinct_ops)] = .{
81 .llvm_name = "distinct-ops",
82 .description = "Assume that the distinct-operands facility is installed",
83 .dependencies = featureSet(&[_]Feature{}),
84 };
85 result[@enumToInt(Feature.enhanced_dat_2)] = .{
86 .llvm_name = "enhanced-dat-2",
87 .description = "Assume that the enhanced-DAT facility 2 is installed",
88 .dependencies = featureSet(&[_]Feature{}),
89 };
90 result[@enumToInt(Feature.enhanced_sort)] = .{
91 .llvm_name = "enhanced-sort",
92 .description = "Assume that the enhanced-sort facility is installed",
93 .dependencies = featureSet(&[_]Feature{}),
94 };
95 result[@enumToInt(Feature.execution_hint)] = .{
96 .llvm_name = "execution-hint",
97 .description = "Assume that the execution-hint facility is installed",
98 .dependencies = featureSet(&[_]Feature{}),
99 };
100 result[@enumToInt(Feature.fast_serialization)] = .{
101 .llvm_name = "fast-serialization",
102 .description = "Assume that the fast-serialization facility is installed",
103 .dependencies = featureSet(&[_]Feature{}),
104 };
105 result[@enumToInt(Feature.fp_extension)] = .{
106 .llvm_name = "fp-extension",
107 .description = "Assume that the floating-point extension facility is installed",
108 .dependencies = featureSet(&[_]Feature{}),
109 };
110 result[@enumToInt(Feature.guarded_storage)] = .{
111 .llvm_name = "guarded-storage",
112 .description = "Assume that the guarded-storage facility is installed",
113 .dependencies = featureSet(&[_]Feature{}),
114 };
115 result[@enumToInt(Feature.high_word)] = .{
116 .llvm_name = "high-word",
117 .description = "Assume that the high-word facility is installed",
118 .dependencies = featureSet(&[_]Feature{}),
119 };
120 result[@enumToInt(Feature.insert_reference_bits_multiple)] = .{
121 .llvm_name = "insert-reference-bits-multiple",
122 .description = "Assume that the insert-reference-bits-multiple facility is installed",
123 .dependencies = featureSet(&[_]Feature{}),
124 };
125 result[@enumToInt(Feature.interlocked_access1)] = .{
126 .llvm_name = "interlocked-access1",
127 .description = "Assume that interlocked-access facility 1 is installed",
128 .dependencies = featureSet(&[_]Feature{}),
129 };
130 result[@enumToInt(Feature.load_and_trap)] = .{
131 .llvm_name = "load-and-trap",
132 .description = "Assume that the load-and-trap facility is installed",
133 .dependencies = featureSet(&[_]Feature{}),
134 };
135 result[@enumToInt(Feature.load_and_zero_rightmost_byte)] = .{
136 .llvm_name = "load-and-zero-rightmost-byte",
137 .description = "Assume that the load-and-zero-rightmost-byte facility is installed",
138 .dependencies = featureSet(&[_]Feature{}),
139 };
140 result[@enumToInt(Feature.load_store_on_cond)] = .{
141 .llvm_name = "load-store-on-cond",
142 .description = "Assume that the load/store-on-condition facility is installed",
143 .dependencies = featureSet(&[_]Feature{}),
144 };
145 result[@enumToInt(Feature.load_store_on_cond_2)] = .{
146 .llvm_name = "load-store-on-cond-2",
147 .description = "Assume that the load/store-on-condition facility 2 is installed",
148 .dependencies = featureSet(&[_]Feature{}),
149 };
150 result[@enumToInt(Feature.message_security_assist_extension3)] = .{
151 .llvm_name = "message-security-assist-extension3",
152 .description = "Assume that the message-security-assist extension facility 3 is installed",
153 .dependencies = featureSet(&[_]Feature{}),
154 };
155 result[@enumToInt(Feature.message_security_assist_extension4)] = .{
156 .llvm_name = "message-security-assist-extension4",
157 .description = "Assume that the message-security-assist extension facility 4 is installed",
158 .dependencies = featureSet(&[_]Feature{}),
159 };
160 result[@enumToInt(Feature.message_security_assist_extension5)] = .{
161 .llvm_name = "message-security-assist-extension5",
162 .description = "Assume that the message-security-assist extension facility 5 is installed",
163 .dependencies = featureSet(&[_]Feature{}),
164 };
165 result[@enumToInt(Feature.message_security_assist_extension7)] = .{
166 .llvm_name = "message-security-assist-extension7",
167 .description = "Assume that the message-security-assist extension facility 7 is installed",
168 .dependencies = featureSet(&[_]Feature{}),
169 };
170 result[@enumToInt(Feature.message_security_assist_extension8)] = .{
171 .llvm_name = "message-security-assist-extension8",
172 .description = "Assume that the message-security-assist extension facility 8 is installed",
173 .dependencies = featureSet(&[_]Feature{}),
174 };
175 result[@enumToInt(Feature.message_security_assist_extension9)] = .{
176 .llvm_name = "message-security-assist-extension9",
177 .description = "Assume that the message-security-assist extension facility 9 is installed",
178 .dependencies = featureSet(&[_]Feature{}),
179 };
180 result[@enumToInt(Feature.miscellaneous_extensions)] = .{
181 .llvm_name = "miscellaneous-extensions",
182 .description = "Assume that the miscellaneous-extensions facility is installed",
183 .dependencies = featureSet(&[_]Feature{}),
184 };
185 result[@enumToInt(Feature.miscellaneous_extensions_2)] = .{
186 .llvm_name = "miscellaneous-extensions-2",
187 .description = "Assume that the miscellaneous-extensions facility 2 is installed",
188 .dependencies = featureSet(&[_]Feature{}),
189 };
190 result[@enumToInt(Feature.miscellaneous_extensions_3)] = .{
191 .llvm_name = "miscellaneous-extensions-3",
192 .description = "Assume that the miscellaneous-extensions facility 3 is installed",
193 .dependencies = featureSet(&[_]Feature{}),
194 };
195 result[@enumToInt(Feature.nnp_assist)] = .{
196 .llvm_name = "nnp-assist",
197 .description = "Assume that the NNP-assist facility is installed",
198 .dependencies = featureSet(&[_]Feature{}),
199 };
200 result[@enumToInt(Feature.population_count)] = .{
201 .llvm_name = "population-count",
202 .description = "Assume that the population-count facility is installed",
203 .dependencies = featureSet(&[_]Feature{}),
204 };
205 result[@enumToInt(Feature.processor_activity_instrumentation)] = .{
206 .llvm_name = "processor-activity-instrumentation",
207 .description = "Assume that the processor-activity-instrumentation facility is installed",
208 .dependencies = featureSet(&[_]Feature{}),
209 };
210 result[@enumToInt(Feature.processor_assist)] = .{
211 .llvm_name = "processor-assist",
212 .description = "Assume that the processor-assist facility is installed",
213 .dependencies = featureSet(&[_]Feature{}),
214 };
215 result[@enumToInt(Feature.reset_dat_protection)] = .{
216 .llvm_name = "reset-dat-protection",
217 .description = "Assume that the reset-DAT-protection facility is installed",
218 .dependencies = featureSet(&[_]Feature{}),
219 };
220 result[@enumToInt(Feature.reset_reference_bits_multiple)] = .{
221 .llvm_name = "reset-reference-bits-multiple",
222 .description = "Assume that the reset-reference-bits-multiple facility is installed",
223 .dependencies = featureSet(&[_]Feature{}),
224 };
225 result[@enumToInt(Feature.soft_float)] = .{
226 .llvm_name = "soft-float",
227 .description = "Use software emulation for floating point",
228 .dependencies = featureSet(&[_]Feature{}),
229 };
230 result[@enumToInt(Feature.transactional_execution)] = .{
231 .llvm_name = "transactional-execution",
232 .description = "Assume that the transactional-execution facility is installed",
233 .dependencies = featureSet(&[_]Feature{}),
234 };
235 result[@enumToInt(Feature.vector)] = .{
236 .llvm_name = "vector",
237 .description = "Assume that the vectory facility is installed",
238 .dependencies = featureSet(&[_]Feature{}),
239 };
240 result[@enumToInt(Feature.vector_enhancements_1)] = .{
241 .llvm_name = "vector-enhancements-1",
242 .description = "Assume that the vector enhancements facility 1 is installed",
243 .dependencies = featureSet(&[_]Feature{}),
244 };
245 result[@enumToInt(Feature.vector_enhancements_2)] = .{
246 .llvm_name = "vector-enhancements-2",
247 .description = "Assume that the vector enhancements facility 2 is installed",
248 .dependencies = featureSet(&[_]Feature{}),
249 };
250 result[@enumToInt(Feature.vector_packed_decimal)] = .{
251 .llvm_name = "vector-packed-decimal",
252 .description = "Assume that the vector packed decimal facility is installed",
253 .dependencies = featureSet(&[_]Feature{}),
254 };
255 result[@enumToInt(Feature.vector_packed_decimal_enhancement)] = .{
256 .llvm_name = "vector-packed-decimal-enhancement",
257 .description = "Assume that the vector packed decimal enhancement facility is installed",
258 .dependencies = featureSet(&[_]Feature{}),
259 };
260 result[@enumToInt(Feature.vector_packed_decimal_enhancement_2)] = .{
261 .llvm_name = "vector-packed-decimal-enhancement-2",
262 .description = "Assume that the vector packed decimal enhancement facility 2 is installed",
263 .dependencies = featureSet(&[_]Feature{}),
264 };
265 const ti = @typeInfo(Feature);
266 for (result) |*elem, i| {
267 elem.index = i;
268 elem.name = ti.Enum.fields[i].name;
269 }
270 break :blk result;
271};
272
273pub const cpu = struct {
274 pub const arch10 = CpuModel{
275 .name = "arch10",
276 .llvm_name = "arch10",
277 .features = featureSet(&[_]Feature{
278 .dfp_zoned_conversion,
279 .distinct_ops,
280 .enhanced_dat_2,
281 .execution_hint,
282 .fast_serialization,
283 .fp_extension,
284 .high_word,
285 .interlocked_access1,
286 .load_and_trap,
287 .load_store_on_cond,
288 .message_security_assist_extension3,
289 .message_security_assist_extension4,
290 .miscellaneous_extensions,
291 .population_count,
292 .processor_assist,
293 .reset_reference_bits_multiple,
294 .transactional_execution,
295 }),
296 };
297 pub const arch11 = CpuModel{
298 .name = "arch11",
299 .llvm_name = "arch11",
300 .features = featureSet(&[_]Feature{
301 .dfp_packed_conversion,
302 .dfp_zoned_conversion,
303 .distinct_ops,
304 .enhanced_dat_2,
305 .execution_hint,
306 .fast_serialization,
307 .fp_extension,
308 .high_word,
309 .interlocked_access1,
310 .load_and_trap,
311 .load_and_zero_rightmost_byte,
312 .load_store_on_cond,
313 .load_store_on_cond_2,
314 .message_security_assist_extension3,
315 .message_security_assist_extension4,
316 .message_security_assist_extension5,
317 .miscellaneous_extensions,
318 .population_count,
319 .processor_assist,
320 .reset_reference_bits_multiple,
321 .transactional_execution,
322 .vector,
323 }),
324 };
325 pub const arch12 = CpuModel{
326 .name = "arch12",
327 .llvm_name = "arch12",
328 .features = featureSet(&[_]Feature{
329 .dfp_packed_conversion,
330 .dfp_zoned_conversion,
331 .distinct_ops,
332 .enhanced_dat_2,
333 .execution_hint,
334 .fast_serialization,
335 .fp_extension,
336 .guarded_storage,
337 .high_word,
338 .insert_reference_bits_multiple,
339 .interlocked_access1,
340 .load_and_trap,
341 .load_and_zero_rightmost_byte,
342 .load_store_on_cond,
343 .load_store_on_cond_2,
344 .message_security_assist_extension3,
345 .message_security_assist_extension4,
346 .message_security_assist_extension5,
347 .message_security_assist_extension7,
348 .message_security_assist_extension8,
349 .miscellaneous_extensions,
350 .miscellaneous_extensions_2,
351 .population_count,
352 .processor_assist,
353 .reset_reference_bits_multiple,
354 .transactional_execution,
355 .vector,
356 .vector_enhancements_1,
357 .vector_packed_decimal,
358 }),
359 };
360 pub const arch13 = CpuModel{
361 .name = "arch13",
362 .llvm_name = "arch13",
363 .features = featureSet(&[_]Feature{
364 .deflate_conversion,
365 .dfp_packed_conversion,
366 .dfp_zoned_conversion,
367 .distinct_ops,
368 .enhanced_dat_2,
369 .enhanced_sort,
370 .execution_hint,
371 .fast_serialization,
372 .fp_extension,
373 .guarded_storage,
374 .high_word,
375 .insert_reference_bits_multiple,
376 .interlocked_access1,
377 .load_and_trap,
378 .load_and_zero_rightmost_byte,
379 .load_store_on_cond,
380 .load_store_on_cond_2,
381 .message_security_assist_extension3,
382 .message_security_assist_extension4,
383 .message_security_assist_extension5,
384 .message_security_assist_extension7,
385 .message_security_assist_extension8,
386 .message_security_assist_extension9,
387 .miscellaneous_extensions,
388 .miscellaneous_extensions_2,
389 .miscellaneous_extensions_3,
390 .population_count,
391 .processor_assist,
392 .reset_reference_bits_multiple,
393 .transactional_execution,
394 .vector,
395 .vector_enhancements_1,
396 .vector_enhancements_2,
397 .vector_packed_decimal,
398 .vector_packed_decimal_enhancement,
399 }),
400 };
401 pub const arch14 = CpuModel{
402 .name = "arch14",
403 .llvm_name = "arch14",
404 .features = featureSet(&[_]Feature{
405 .bear_enhancement,
406 .deflate_conversion,
407 .dfp_packed_conversion,
408 .dfp_zoned_conversion,
409 .distinct_ops,
410 .enhanced_dat_2,
411 .enhanced_sort,
412 .execution_hint,
413 .fast_serialization,
414 .fp_extension,
415 .guarded_storage,
416 .high_word,
417 .insert_reference_bits_multiple,
418 .interlocked_access1,
419 .load_and_trap,
420 .load_and_zero_rightmost_byte,
421 .load_store_on_cond,
422 .load_store_on_cond_2,
423 .message_security_assist_extension3,
424 .message_security_assist_extension4,
425 .message_security_assist_extension5,
426 .message_security_assist_extension7,
427 .message_security_assist_extension8,
428 .message_security_assist_extension9,
429 .miscellaneous_extensions,
430 .miscellaneous_extensions_2,
431 .miscellaneous_extensions_3,
432 .nnp_assist,
433 .population_count,
434 .processor_activity_instrumentation,
435 .processor_assist,
436 .reset_dat_protection,
437 .reset_reference_bits_multiple,
438 .transactional_execution,
439 .vector,
440 .vector_enhancements_1,
441 .vector_enhancements_2,
442 .vector_packed_decimal,
443 .vector_packed_decimal_enhancement,
444 .vector_packed_decimal_enhancement_2,
445 }),
446 };
447 pub const arch8 = CpuModel{
448 .name = "arch8",
449 .llvm_name = "arch8",
450 .features = featureSet(&[_]Feature{}),
451 };
452 pub const arch9 = CpuModel{
453 .name = "arch9",
454 .llvm_name = "arch9",
455 .features = featureSet(&[_]Feature{
456 .distinct_ops,
457 .fast_serialization,
458 .fp_extension,
459 .high_word,
460 .interlocked_access1,
461 .load_store_on_cond,
462 .message_security_assist_extension3,
463 .message_security_assist_extension4,
464 .population_count,
465 .reset_reference_bits_multiple,
466 }),
467 };
468 pub const generic = CpuModel{
469 .name = "generic",
470 .llvm_name = "generic",
471 .features = featureSet(&[_]Feature{}),
472 };
473 pub const z10 = CpuModel{
474 .name = "z10",
475 .llvm_name = "z10",
476 .features = featureSet(&[_]Feature{}),
477 };
478 pub const z13 = CpuModel{
479 .name = "z13",
480 .llvm_name = "z13",
481 .features = featureSet(&[_]Feature{
482 .dfp_packed_conversion,
483 .dfp_zoned_conversion,
484 .distinct_ops,
485 .enhanced_dat_2,
486 .execution_hint,
487 .fast_serialization,
488 .fp_extension,
489 .high_word,
490 .interlocked_access1,
491 .load_and_trap,
492 .load_and_zero_rightmost_byte,
493 .load_store_on_cond,
494 .load_store_on_cond_2,
495 .message_security_assist_extension3,
496 .message_security_assist_extension4,
497 .message_security_assist_extension5,
498 .miscellaneous_extensions,
499 .population_count,
500 .processor_assist,
501 .reset_reference_bits_multiple,
502 .transactional_execution,
503 .vector,
504 }),
505 };
506 pub const z14 = CpuModel{
507 .name = "z14",
508 .llvm_name = "z14",
509 .features = featureSet(&[_]Feature{
510 .dfp_packed_conversion,
511 .dfp_zoned_conversion,
512 .distinct_ops,
513 .enhanced_dat_2,
514 .execution_hint,
515 .fast_serialization,
516 .fp_extension,
517 .guarded_storage,
518 .high_word,
519 .insert_reference_bits_multiple,
520 .interlocked_access1,
521 .load_and_trap,
522 .load_and_zero_rightmost_byte,
523 .load_store_on_cond,
524 .load_store_on_cond_2,
525 .message_security_assist_extension3,
526 .message_security_assist_extension4,
527 .message_security_assist_extension5,
528 .message_security_assist_extension7,
529 .message_security_assist_extension8,
530 .miscellaneous_extensions,
531 .miscellaneous_extensions_2,
532 .population_count,
533 .processor_assist,
534 .reset_reference_bits_multiple,
535 .transactional_execution,
536 .vector,
537 .vector_enhancements_1,
538 .vector_packed_decimal,
539 }),
540 };
541 pub const z15 = CpuModel{
542 .name = "z15",
543 .llvm_name = "z15",
544 .features = featureSet(&[_]Feature{
545 .deflate_conversion,
546 .dfp_packed_conversion,
547 .dfp_zoned_conversion,
548 .distinct_ops,
549 .enhanced_dat_2,
550 .enhanced_sort,
551 .execution_hint,
552 .fast_serialization,
553 .fp_extension,
554 .guarded_storage,
555 .high_word,
556 .insert_reference_bits_multiple,
557 .interlocked_access1,
558 .load_and_trap,
559 .load_and_zero_rightmost_byte,
560 .load_store_on_cond,
561 .load_store_on_cond_2,
562 .message_security_assist_extension3,
563 .message_security_assist_extension4,
564 .message_security_assist_extension5,
565 .message_security_assist_extension7,
566 .message_security_assist_extension8,
567 .message_security_assist_extension9,
568 .miscellaneous_extensions,
569 .miscellaneous_extensions_2,
570 .miscellaneous_extensions_3,
571 .population_count,
572 .processor_assist,
573 .reset_reference_bits_multiple,
574 .transactional_execution,
575 .vector,
576 .vector_enhancements_1,
577 .vector_enhancements_2,
578 .vector_packed_decimal,
579 .vector_packed_decimal_enhancement,
580 }),
581 };
582 pub const z196 = CpuModel{
583 .name = "z196",
584 .llvm_name = "z196",
585 .features = featureSet(&[_]Feature{
586 .distinct_ops,
587 .fast_serialization,
588 .fp_extension,
589 .high_word,
590 .interlocked_access1,
591 .load_store_on_cond,
592 .message_security_assist_extension3,
593 .message_security_assist_extension4,
594 .population_count,
595 .reset_reference_bits_multiple,
596 }),
597 };
598 pub const zEC12 = CpuModel{
599 .name = "zEC12",
600 .llvm_name = "zEC12",
601 .features = featureSet(&[_]Feature{
602 .dfp_zoned_conversion,
603 .distinct_ops,
604 .enhanced_dat_2,
605 .execution_hint,
606 .fast_serialization,
607 .fp_extension,
608 .high_word,
609 .interlocked_access1,
610 .load_and_trap,
611 .load_store_on_cond,
612 .message_security_assist_extension3,
613 .message_security_assist_extension4,
614 .miscellaneous_extensions,
615 .population_count,
616 .processor_assist,
617 .reset_reference_bits_multiple,
618 .transactional_execution,
619 }),
620 };
621};
lib/std/target/systemz.zig deleted-621
......@@ -1,621 +0,0 @@
1//! This file is auto-generated by tools/update_cpu_features.zig.
2
3const std = @import("../std.zig");
4const CpuFeature = std.Target.Cpu.Feature;
5const CpuModel = std.Target.Cpu.Model;
6
7pub const Feature = enum {
8 bear_enhancement,
9 deflate_conversion,
10 dfp_packed_conversion,
11 dfp_zoned_conversion,
12 distinct_ops,
13 enhanced_dat_2,
14 enhanced_sort,
15 execution_hint,
16 fast_serialization,
17 fp_extension,
18 guarded_storage,
19 high_word,
20 insert_reference_bits_multiple,
21 interlocked_access1,
22 load_and_trap,
23 load_and_zero_rightmost_byte,
24 load_store_on_cond,
25 load_store_on_cond_2,
26 message_security_assist_extension3,
27 message_security_assist_extension4,
28 message_security_assist_extension5,
29 message_security_assist_extension7,
30 message_security_assist_extension8,
31 message_security_assist_extension9,
32 miscellaneous_extensions,
33 miscellaneous_extensions_2,
34 miscellaneous_extensions_3,
35 nnp_assist,
36 population_count,
37 processor_activity_instrumentation,
38 processor_assist,
39 reset_dat_protection,
40 reset_reference_bits_multiple,
41 soft_float,
42 transactional_execution,
43 vector,
44 vector_enhancements_1,
45 vector_enhancements_2,
46 vector_packed_decimal,
47 vector_packed_decimal_enhancement,
48 vector_packed_decimal_enhancement_2,
49};
50
51pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet;
52pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas;
53pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny;
54pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll;
55
56pub const all_features = blk: {
57 const len = @typeInfo(Feature).Enum.fields.len;
58 std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
59 var result: [len]CpuFeature = undefined;
60 result[@enumToInt(Feature.bear_enhancement)] = .{
61 .llvm_name = "bear-enhancement",
62 .description = "Assume that the BEAR-enhancement facility is installed",
63 .dependencies = featureSet(&[_]Feature{}),
64 };
65 result[@enumToInt(Feature.deflate_conversion)] = .{
66 .llvm_name = "deflate-conversion",
67 .description = "Assume that the deflate-conversion facility is installed",
68 .dependencies = featureSet(&[_]Feature{}),
69 };
70 result[@enumToInt(Feature.dfp_packed_conversion)] = .{
71 .llvm_name = "dfp-packed-conversion",
72 .description = "Assume that the DFP packed-conversion facility is installed",
73 .dependencies = featureSet(&[_]Feature{}),
74 };
75 result[@enumToInt(Feature.dfp_zoned_conversion)] = .{
76 .llvm_name = "dfp-zoned-conversion",
77 .description = "Assume that the DFP zoned-conversion facility is installed",
78 .dependencies = featureSet(&[_]Feature{}),
79 };
80 result[@enumToInt(Feature.distinct_ops)] = .{
81 .llvm_name = "distinct-ops",
82 .description = "Assume that the distinct-operands facility is installed",
83 .dependencies = featureSet(&[_]Feature{}),
84 };
85 result[@enumToInt(Feature.enhanced_dat_2)] = .{
86 .llvm_name = "enhanced-dat-2",
87 .description = "Assume that the enhanced-DAT facility 2 is installed",
88 .dependencies = featureSet(&[_]Feature{}),
89 };
90 result[@enumToInt(Feature.enhanced_sort)] = .{
91 .llvm_name = "enhanced-sort",
92 .description = "Assume that the enhanced-sort facility is installed",
93 .dependencies = featureSet(&[_]Feature{}),
94 };
95 result[@enumToInt(Feature.execution_hint)] = .{
96 .llvm_name = "execution-hint",
97 .description = "Assume that the execution-hint facility is installed",
98 .dependencies = featureSet(&[_]Feature{}),
99 };
100 result[@enumToInt(Feature.fast_serialization)] = .{
101 .llvm_name = "fast-serialization",
102 .description = "Assume that the fast-serialization facility is installed",
103 .dependencies = featureSet(&[_]Feature{}),
104 };
105 result[@enumToInt(Feature.fp_extension)] = .{
106 .llvm_name = "fp-extension",
107 .description = "Assume that the floating-point extension facility is installed",
108 .dependencies = featureSet(&[_]Feature{}),
109 };
110 result[@enumToInt(Feature.guarded_storage)] = .{
111 .llvm_name = "guarded-storage",
112 .description = "Assume that the guarded-storage facility is installed",
113 .dependencies = featureSet(&[_]Feature{}),
114 };
115 result[@enumToInt(Feature.high_word)] = .{
116 .llvm_name = "high-word",
117 .description = "Assume that the high-word facility is installed",
118 .dependencies = featureSet(&[_]Feature{}),
119 };
120 result[@enumToInt(Feature.insert_reference_bits_multiple)] = .{
121 .llvm_name = "insert-reference-bits-multiple",
122 .description = "Assume that the insert-reference-bits-multiple facility is installed",
123 .dependencies = featureSet(&[_]Feature{}),
124 };
125 result[@enumToInt(Feature.interlocked_access1)] = .{
126 .llvm_name = "interlocked-access1",
127 .description = "Assume that interlocked-access facility 1 is installed",
128 .dependencies = featureSet(&[_]Feature{}),
129 };
130 result[@enumToInt(Feature.load_and_trap)] = .{
131 .llvm_name = "load-and-trap",
132 .description = "Assume that the load-and-trap facility is installed",
133 .dependencies = featureSet(&[_]Feature{}),
134 };
135 result[@enumToInt(Feature.load_and_zero_rightmost_byte)] = .{
136 .llvm_name = "load-and-zero-rightmost-byte",
137 .description = "Assume that the load-and-zero-rightmost-byte facility is installed",
138 .dependencies = featureSet(&[_]Feature{}),
139 };
140 result[@enumToInt(Feature.load_store_on_cond)] = .{
141 .llvm_name = "load-store-on-cond",
142 .description = "Assume that the load/store-on-condition facility is installed",
143 .dependencies = featureSet(&[_]Feature{}),
144 };
145 result[@enumToInt(Feature.load_store_on_cond_2)] = .{
146 .llvm_name = "load-store-on-cond-2",
147 .description = "Assume that the load/store-on-condition facility 2 is installed",
148 .dependencies = featureSet(&[_]Feature{}),
149 };
150 result[@enumToInt(Feature.message_security_assist_extension3)] = .{
151 .llvm_name = "message-security-assist-extension3",
152 .description = "Assume that the message-security-assist extension facility 3 is installed",
153 .dependencies = featureSet(&[_]Feature{}),
154 };
155 result[@enumToInt(Feature.message_security_assist_extension4)] = .{
156 .llvm_name = "message-security-assist-extension4",
157 .description = "Assume that the message-security-assist extension facility 4 is installed",
158 .dependencies = featureSet(&[_]Feature{}),
159 };
160 result[@enumToInt(Feature.message_security_assist_extension5)] = .{
161 .llvm_name = "message-security-assist-extension5",
162 .description = "Assume that the message-security-assist extension facility 5 is installed",
163 .dependencies = featureSet(&[_]Feature{}),
164 };
165 result[@enumToInt(Feature.message_security_assist_extension7)] = .{
166 .llvm_name = "message-security-assist-extension7",
167 .description = "Assume that the message-security-assist extension facility 7 is installed",
168 .dependencies = featureSet(&[_]Feature{}),
169 };
170 result[@enumToInt(Feature.message_security_assist_extension8)] = .{
171 .llvm_name = "message-security-assist-extension8",
172 .description = "Assume that the message-security-assist extension facility 8 is installed",
173 .dependencies = featureSet(&[_]Feature{}),
174 };
175 result[@enumToInt(Feature.message_security_assist_extension9)] = .{
176 .llvm_name = "message-security-assist-extension9",
177 .description = "Assume that the message-security-assist extension facility 9 is installed",
178 .dependencies = featureSet(&[_]Feature{}),
179 };
180 result[@enumToInt(Feature.miscellaneous_extensions)] = .{
181 .llvm_name = "miscellaneous-extensions",
182 .description = "Assume that the miscellaneous-extensions facility is installed",
183 .dependencies = featureSet(&[_]Feature{}),
184 };
185 result[@enumToInt(Feature.miscellaneous_extensions_2)] = .{
186 .llvm_name = "miscellaneous-extensions-2",
187 .description = "Assume that the miscellaneous-extensions facility 2 is installed",
188 .dependencies = featureSet(&[_]Feature{}),
189 };
190 result[@enumToInt(Feature.miscellaneous_extensions_3)] = .{
191 .llvm_name = "miscellaneous-extensions-3",
192 .description = "Assume that the miscellaneous-extensions facility 3 is installed",
193 .dependencies = featureSet(&[_]Feature{}),
194 };
195 result[@enumToInt(Feature.nnp_assist)] = .{
196 .llvm_name = "nnp-assist",
197 .description = "Assume that the NNP-assist facility is installed",
198 .dependencies = featureSet(&[_]Feature{}),
199 };
200 result[@enumToInt(Feature.population_count)] = .{
201 .llvm_name = "population-count",
202 .description = "Assume that the population-count facility is installed",
203 .dependencies = featureSet(&[_]Feature{}),
204 };
205 result[@enumToInt(Feature.processor_activity_instrumentation)] = .{
206 .llvm_name = "processor-activity-instrumentation",
207 .description = "Assume that the processor-activity-instrumentation facility is installed",
208 .dependencies = featureSet(&[_]Feature{}),
209 };
210 result[@enumToInt(Feature.processor_assist)] = .{
211 .llvm_name = "processor-assist",
212 .description = "Assume that the processor-assist facility is installed",
213 .dependencies = featureSet(&[_]Feature{}),
214 };
215 result[@enumToInt(Feature.reset_dat_protection)] = .{
216 .llvm_name = "reset-dat-protection",
217 .description = "Assume that the reset-DAT-protection facility is installed",
218 .dependencies = featureSet(&[_]Feature{}),
219 };
220 result[@enumToInt(Feature.reset_reference_bits_multiple)] = .{
221 .llvm_name = "reset-reference-bits-multiple",
222 .description = "Assume that the reset-reference-bits-multiple facility is installed",
223 .dependencies = featureSet(&[_]Feature{}),
224 };
225 result[@enumToInt(Feature.soft_float)] = .{
226 .llvm_name = "soft-float",
227 .description = "Use software emulation for floating point",
228 .dependencies = featureSet(&[_]Feature{}),
229 };
230 result[@enumToInt(Feature.transactional_execution)] = .{
231 .llvm_name = "transactional-execution",
232 .description = "Assume that the transactional-execution facility is installed",
233 .dependencies = featureSet(&[_]Feature{}),
234 };
235 result[@enumToInt(Feature.vector)] = .{
236 .llvm_name = "vector",
237 .description = "Assume that the vectory facility is installed",
238 .dependencies = featureSet(&[_]Feature{}),
239 };
240 result[@enumToInt(Feature.vector_enhancements_1)] = .{
241 .llvm_name = "vector-enhancements-1",
242 .description = "Assume that the vector enhancements facility 1 is installed",
243 .dependencies = featureSet(&[_]Feature{}),
244 };
245 result[@enumToInt(Feature.vector_enhancements_2)] = .{
246 .llvm_name = "vector-enhancements-2",
247 .description = "Assume that the vector enhancements facility 2 is installed",
248 .dependencies = featureSet(&[_]Feature{}),
249 };
250 result[@enumToInt(Feature.vector_packed_decimal)] = .{
251 .llvm_name = "vector-packed-decimal",
252 .description = "Assume that the vector packed decimal facility is installed",
253 .dependencies = featureSet(&[_]Feature{}),
254 };
255 result[@enumToInt(Feature.vector_packed_decimal_enhancement)] = .{
256 .llvm_name = "vector-packed-decimal-enhancement",
257 .description = "Assume that the vector packed decimal enhancement facility is installed",
258 .dependencies = featureSet(&[_]Feature{}),
259 };
260 result[@enumToInt(Feature.vector_packed_decimal_enhancement_2)] = .{
261 .llvm_name = "vector-packed-decimal-enhancement-2",
262 .description = "Assume that the vector packed decimal enhancement facility 2 is installed",
263 .dependencies = featureSet(&[_]Feature{}),
264 };
265 const ti = @typeInfo(Feature);
266 for (result) |*elem, i| {
267 elem.index = i;
268 elem.name = ti.Enum.fields[i].name;
269 }
270 break :blk result;
271};
272
273pub const cpu = struct {
274 pub const arch10 = CpuModel{
275 .name = "arch10",
276 .llvm_name = "arch10",
277 .features = featureSet(&[_]Feature{
278 .dfp_zoned_conversion,
279 .distinct_ops,
280 .enhanced_dat_2,
281 .execution_hint,
282 .fast_serialization,
283 .fp_extension,
284 .high_word,
285 .interlocked_access1,
286 .load_and_trap,
287 .load_store_on_cond,
288 .message_security_assist_extension3,
289 .message_security_assist_extension4,
290 .miscellaneous_extensions,
291 .population_count,
292 .processor_assist,
293 .reset_reference_bits_multiple,
294 .transactional_execution,
295 }),
296 };
297 pub const arch11 = CpuModel{
298 .name = "arch11",
299 .llvm_name = "arch11",
300 .features = featureSet(&[_]Feature{
301 .dfp_packed_conversion,
302 .dfp_zoned_conversion,
303 .distinct_ops,
304 .enhanced_dat_2,
305 .execution_hint,
306 .fast_serialization,
307 .fp_extension,
308 .high_word,
309 .interlocked_access1,
310 .load_and_trap,
311 .load_and_zero_rightmost_byte,
312 .load_store_on_cond,
313 .load_store_on_cond_2,
314 .message_security_assist_extension3,
315 .message_security_assist_extension4,
316 .message_security_assist_extension5,
317 .miscellaneous_extensions,
318 .population_count,
319 .processor_assist,
320 .reset_reference_bits_multiple,
321 .transactional_execution,
322 .vector,
323 }),
324 };
325 pub const arch12 = CpuModel{
326 .name = "arch12",
327 .llvm_name = "arch12",
328 .features = featureSet(&[_]Feature{
329 .dfp_packed_conversion,
330 .dfp_zoned_conversion,
331 .distinct_ops,
332 .enhanced_dat_2,
333 .execution_hint,
334 .fast_serialization,
335 .fp_extension,
336 .guarded_storage,
337 .high_word,
338 .insert_reference_bits_multiple,
339 .interlocked_access1,
340 .load_and_trap,
341 .load_and_zero_rightmost_byte,
342 .load_store_on_cond,
343 .load_store_on_cond_2,
344 .message_security_assist_extension3,
345 .message_security_assist_extension4,
346 .message_security_assist_extension5,
347 .message_security_assist_extension7,
348 .message_security_assist_extension8,
349 .miscellaneous_extensions,
350 .miscellaneous_extensions_2,
351 .population_count,
352 .processor_assist,
353 .reset_reference_bits_multiple,
354 .transactional_execution,
355 .vector,
356 .vector_enhancements_1,
357 .vector_packed_decimal,
358 }),
359 };
360 pub const arch13 = CpuModel{
361 .name = "arch13",
362 .llvm_name = "arch13",
363 .features = featureSet(&[_]Feature{
364 .deflate_conversion,
365 .dfp_packed_conversion,
366 .dfp_zoned_conversion,
367 .distinct_ops,
368 .enhanced_dat_2,
369 .enhanced_sort,
370 .execution_hint,
371 .fast_serialization,
372 .fp_extension,
373 .guarded_storage,
374 .high_word,
375 .insert_reference_bits_multiple,
376 .interlocked_access1,
377 .load_and_trap,
378 .load_and_zero_rightmost_byte,
379 .load_store_on_cond,
380 .load_store_on_cond_2,
381 .message_security_assist_extension3,
382 .message_security_assist_extension4,
383 .message_security_assist_extension5,
384 .message_security_assist_extension7,
385 .message_security_assist_extension8,
386 .message_security_assist_extension9,
387 .miscellaneous_extensions,
388 .miscellaneous_extensions_2,
389 .miscellaneous_extensions_3,
390 .population_count,
391 .processor_assist,
392 .reset_reference_bits_multiple,
393 .transactional_execution,
394 .vector,
395 .vector_enhancements_1,
396 .vector_enhancements_2,
397 .vector_packed_decimal,
398 .vector_packed_decimal_enhancement,
399 }),
400 };
401 pub const arch14 = CpuModel{
402 .name = "arch14",
403 .llvm_name = "arch14",
404 .features = featureSet(&[_]Feature{
405 .bear_enhancement,
406 .deflate_conversion,
407 .dfp_packed_conversion,
408 .dfp_zoned_conversion,
409 .distinct_ops,
410 .enhanced_dat_2,
411 .enhanced_sort,
412 .execution_hint,
413 .fast_serialization,
414 .fp_extension,
415 .guarded_storage,
416 .high_word,
417 .insert_reference_bits_multiple,
418 .interlocked_access1,
419 .load_and_trap,
420 .load_and_zero_rightmost_byte,
421 .load_store_on_cond,
422 .load_store_on_cond_2,
423 .message_security_assist_extension3,
424 .message_security_assist_extension4,
425 .message_security_assist_extension5,
426 .message_security_assist_extension7,
427 .message_security_assist_extension8,
428 .message_security_assist_extension9,
429 .miscellaneous_extensions,
430 .miscellaneous_extensions_2,
431 .miscellaneous_extensions_3,
432 .nnp_assist,
433 .population_count,
434 .processor_activity_instrumentation,
435 .processor_assist,
436 .reset_dat_protection,
437 .reset_reference_bits_multiple,
438 .transactional_execution,
439 .vector,
440 .vector_enhancements_1,
441 .vector_enhancements_2,
442 .vector_packed_decimal,
443 .vector_packed_decimal_enhancement,
444 .vector_packed_decimal_enhancement_2,
445 }),
446 };
447 pub const arch8 = CpuModel{
448 .name = "arch8",
449 .llvm_name = "arch8",
450 .features = featureSet(&[_]Feature{}),
451 };
452 pub const arch9 = CpuModel{
453 .name = "arch9",
454 .llvm_name = "arch9",
455 .features = featureSet(&[_]Feature{
456 .distinct_ops,
457 .fast_serialization,
458 .fp_extension,
459 .high_word,
460 .interlocked_access1,
461 .load_store_on_cond,
462 .message_security_assist_extension3,
463 .message_security_assist_extension4,
464 .population_count,
465 .reset_reference_bits_multiple,
466 }),
467 };
468 pub const generic = CpuModel{
469 .name = "generic",
470 .llvm_name = "generic",
471 .features = featureSet(&[_]Feature{}),
472 };
473 pub const z10 = CpuModel{
474 .name = "z10",
475 .llvm_name = "z10",
476 .features = featureSet(&[_]Feature{}),
477 };
478 pub const z13 = CpuModel{
479 .name = "z13",
480 .llvm_name = "z13",
481 .features = featureSet(&[_]Feature{
482 .dfp_packed_conversion,
483 .dfp_zoned_conversion,
484 .distinct_ops,
485 .enhanced_dat_2,
486 .execution_hint,
487 .fast_serialization,
488 .fp_extension,
489 .high_word,
490 .interlocked_access1,
491 .load_and_trap,
492 .load_and_zero_rightmost_byte,
493 .load_store_on_cond,
494 .load_store_on_cond_2,
495 .message_security_assist_extension3,
496 .message_security_assist_extension4,
497 .message_security_assist_extension5,
498 .miscellaneous_extensions,
499 .population_count,
500 .processor_assist,
501 .reset_reference_bits_multiple,
502 .transactional_execution,
503 .vector,
504 }),
505 };
506 pub const z14 = CpuModel{
507 .name = "z14",
508 .llvm_name = "z14",
509 .features = featureSet(&[_]Feature{
510 .dfp_packed_conversion,
511 .dfp_zoned_conversion,
512 .distinct_ops,
513 .enhanced_dat_2,
514 .execution_hint,
515 .fast_serialization,
516 .fp_extension,
517 .guarded_storage,
518 .high_word,
519 .insert_reference_bits_multiple,
520 .interlocked_access1,
521 .load_and_trap,
522 .load_and_zero_rightmost_byte,
523 .load_store_on_cond,
524 .load_store_on_cond_2,
525 .message_security_assist_extension3,
526 .message_security_assist_extension4,
527 .message_security_assist_extension5,
528 .message_security_assist_extension7,
529 .message_security_assist_extension8,
530 .miscellaneous_extensions,
531 .miscellaneous_extensions_2,
532 .population_count,
533 .processor_assist,
534 .reset_reference_bits_multiple,
535 .transactional_execution,
536 .vector,
537 .vector_enhancements_1,
538 .vector_packed_decimal,
539 }),
540 };
541 pub const z15 = CpuModel{
542 .name = "z15",
543 .llvm_name = "z15",
544 .features = featureSet(&[_]Feature{
545 .deflate_conversion,
546 .dfp_packed_conversion,
547 .dfp_zoned_conversion,
548 .distinct_ops,
549 .enhanced_dat_2,
550 .enhanced_sort,
551 .execution_hint,
552 .fast_serialization,
553 .fp_extension,
554 .guarded_storage,
555 .high_word,
556 .insert_reference_bits_multiple,
557 .interlocked_access1,
558 .load_and_trap,
559 .load_and_zero_rightmost_byte,
560 .load_store_on_cond,
561 .load_store_on_cond_2,
562 .message_security_assist_extension3,
563 .message_security_assist_extension4,
564 .message_security_assist_extension5,
565 .message_security_assist_extension7,
566 .message_security_assist_extension8,
567 .message_security_assist_extension9,
568 .miscellaneous_extensions,
569 .miscellaneous_extensions_2,
570 .miscellaneous_extensions_3,
571 .population_count,
572 .processor_assist,
573 .reset_reference_bits_multiple,
574 .transactional_execution,
575 .vector,
576 .vector_enhancements_1,
577 .vector_enhancements_2,
578 .vector_packed_decimal,
579 .vector_packed_decimal_enhancement,
580 }),
581 };
582 pub const z196 = CpuModel{
583 .name = "z196",
584 .llvm_name = "z196",
585 .features = featureSet(&[_]Feature{
586 .distinct_ops,
587 .fast_serialization,
588 .fp_extension,
589 .high_word,
590 .interlocked_access1,
591 .load_store_on_cond,
592 .message_security_assist_extension3,
593 .message_security_assist_extension4,
594 .population_count,
595 .reset_reference_bits_multiple,
596 }),
597 };
598 pub const zEC12 = CpuModel{
599 .name = "zEC12",
600 .llvm_name = "zEC12",
601 .features = featureSet(&[_]Feature{
602 .dfp_zoned_conversion,
603 .distinct_ops,
604 .enhanced_dat_2,
605 .execution_hint,
606 .fast_serialization,
607 .fp_extension,
608 .high_word,
609 .interlocked_access1,
610 .load_and_trap,
611 .load_store_on_cond,
612 .message_security_assist_extension3,
613 .message_security_assist_extension4,
614 .miscellaneous_extensions,
615 .population_count,
616 .processor_assist,
617 .reset_reference_bits_multiple,
618 .transactional_execution,
619 }),
620 };
621};
lib/std/zig/parse.zig+1-1
......@@ -3257,7 +3257,7 @@ const Parser = struct {
32573257 if (p.eatToken(.ellipsis2)) |_| {
32583258 const end_expr = try p.parseExpr();
32593259 if (p.eatToken(.colon)) |_| {
3260 const sentinel = try p.parseExpr();
3260 const sentinel = try p.expectExpr();
32613261 _ = try p.expectToken(.r_bracket);
32623262 return p.addNode(.{
32633263 .tag = .slice_sentinel,
lib/std/zig/parser_test.zig+8
......@@ -5118,6 +5118,14 @@ test "zig fmt: while continue expr" {
51185118 });
51195119}
51205120
5121test "zig fmt: error for missing sentinel value in sentinel slice" {
5122 try testError(
5123 \\const foo = foo[0..:];
5124 , &[_]Error{
5125 .expected_expr,
5126 });
5127}
5128
51215129test "zig fmt: error for invalid bit range" {
51225130 try testError(
51235131 \\var x: []align(0:0:0)u8 = bar;
src/Air.zig+3-2
......@@ -111,8 +111,9 @@ pub const Inst = struct {
111111 div_floor,
112112 /// Same as `div_floor` with optimized float mode.
113113 div_floor_optimized,
114 /// Integer or float division. Guaranteed no remainder.
115 /// For integers, wrapping is undefined behavior.
114 /// Integer or float division.
115 /// If a remainder would be produced, undefined behavior occurs.
116 /// For integers, overflow is undefined behavior.
116117 /// Both operands are guaranteed to be the same type, and the result type
117118 /// is the same as both operands.
118119 /// Uses the `bin_op` field.
src/AstGen.zig+8-1
......@@ -1349,7 +1349,10 @@ fn arrayInitExpr(
13491349 }
13501350 }
13511351 const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
1352 _ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, array_init.ast.type_expr);
1352 _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{
1353 .ty = array_type_inst,
1354 .init_count = @intCast(u32, array_init.ast.elements.len),
1355 });
13531356 break :inst .{
13541357 .array = array_type_inst,
13551358 .elem = .none,
......@@ -1940,6 +1943,9 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
19401943 .break_inline
19411944 else
19421945 .@"break";
1946 if (break_tag == .break_inline) {
1947 _ = try parent_gz.addNode(.check_comptime_control_flow, node);
1948 }
19431949 _ = try parent_gz.addBreak(break_tag, continue_block, .void_value);
19441950 return Zir.Inst.Ref.unreachable_value;
19451951 },
......@@ -2473,6 +2479,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
24732479 .repeat_inline,
24742480 .panic,
24752481 .panic_comptime,
2482 .check_comptime_control_flow,
24762483 => {
24772484 noreturn_src_node = statement;
24782485 break :b true;
src/Compilation.zig-17
......@@ -1494,31 +1494,14 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14941494 );
14951495 errdefer test_pkg.destroy(gpa);
14961496
1497 try test_pkg.add(gpa, "builtin", builtin_pkg);
1498 try test_pkg.add(gpa, "root", test_pkg);
1499 try test_pkg.add(gpa, "std", std_pkg);
1500
15011497 break :root_pkg test_pkg;
15021498 } else main_pkg;
15031499 errdefer if (options.is_test) root_pkg.destroy(gpa);
15041500
1505 var other_pkg_iter = main_pkg.table.valueIterator();
1506 while (other_pkg_iter.next()) |pkg| {
1507 try pkg.*.add(gpa, "builtin", builtin_pkg);
1508 try pkg.*.add(gpa, "std", std_pkg);
1509 }
1510
15111501 try main_pkg.addAndAdopt(gpa, "builtin", builtin_pkg);
15121502 try main_pkg.add(gpa, "root", root_pkg);
15131503 try main_pkg.addAndAdopt(gpa, "std", std_pkg);
15141504
1515 try std_pkg.add(gpa, "builtin", builtin_pkg);
1516 try std_pkg.add(gpa, "root", root_pkg);
1517 try std_pkg.add(gpa, "std", std_pkg);
1518
1519 try builtin_pkg.add(gpa, "std", std_pkg);
1520 try builtin_pkg.add(gpa, "builtin", builtin_pkg);
1521
15221505 const main_pkg_in_std = m: {
15231506 const std_path = try std.fs.path.resolve(arena, &[_][]const u8{
15241507 std_pkg.root_src_directory.path orelse ".",
src/Module.zig+30
......@@ -2283,6 +2283,8 @@ pub const SrcLoc = struct {
22832283 .@"while" => tree.whileFull(node).ast.cond_expr,
22842284 .for_simple => tree.forSimple(node).ast.cond_expr,
22852285 .@"for" => tree.forFull(node).ast.cond_expr,
2286 .@"orelse" => node,
2287 .@"catch" => node,
22862288 else => unreachable,
22872289 };
22882290 return nodeToSpan(tree, src_node);
......@@ -2726,6 +2728,21 @@ pub const SrcLoc = struct {
27262728 };
27272729 return nodeToSpan(tree, full.ast.value_expr);
27282730 },
2731 .node_offset_init_ty => |node_off| {
2732 const tree = try src_loc.file_scope.getTree(gpa);
2733 const node_tags = tree.nodes.items(.tag);
2734 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
2735
2736 var buf: [2]Ast.Node.Index = undefined;
2737 const full: Ast.full.ArrayInit = switch (node_tags[parent_node]) {
2738 .array_init_one, .array_init_one_comma => tree.arrayInitOne(buf[0..1], parent_node),
2739 .array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(&buf, parent_node),
2740 .array_init_dot, .array_init_dot_comma => tree.arrayInitDot(parent_node),
2741 .array_init, .array_init_comma => tree.arrayInit(parent_node),
2742 else => unreachable,
2743 };
2744 return nodeToSpan(tree, full.ast.type_expr);
2745 },
27292746 }
27302747 }
27312748
......@@ -3046,6 +3063,9 @@ pub const LazySrcLoc = union(enum) {
30463063 /// The source location points to the default value of a field.
30473064 /// The Decl is determined contextually.
30483065 node_offset_field_default: i32,
3066 /// The source location points to the type of an array or struct initializer.
3067 /// The Decl is determined contextually.
3068 node_offset_init_ty: i32,
30493069
30503070 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
30513071
......@@ -3124,6 +3144,7 @@ pub const LazySrcLoc = union(enum) {
31243144 .node_offset_ptr_hostsize,
31253145 .node_offset_container_tag,
31263146 .node_offset_field_default,
3147 .node_offset_init_ty,
31273148 => .{
31283149 .file_scope = decl.getFileScope(),
31293150 .parent_decl_node = decl.src_node,
......@@ -4673,6 +4694,15 @@ pub fn importFile(
46734694 cur_file: *File,
46744695 import_string: []const u8,
46754696) !ImportFileResult {
4697 if (std.mem.eql(u8, import_string, "std")) {
4698 return mod.importPkg(mod.main_pkg.table.get("std").?);
4699 }
4700 if (std.mem.eql(u8, import_string, "builtin")) {
4701 return mod.importPkg(mod.main_pkg.table.get("builtin").?);
4702 }
4703 if (std.mem.eql(u8, import_string, "root")) {
4704 return mod.importPkg(mod.root_pkg);
4705 }
46764706 if (cur_file.pkg.table.get(import_string)) |pkg| {
46774707 return mod.importPkg(pkg);
46784708 }
src/Sema.zig+1328-553
......@@ -875,10 +875,6 @@ fn analyzeBodyInner(
875875 .add => try sema.zirArithmetic(block, inst, .add),
876876 .addwrap => try sema.zirArithmetic(block, inst, .addwrap),
877877 .add_sat => try sema.zirArithmetic(block, inst, .add_sat),
878 .div => try sema.zirArithmetic(block, inst, .div),
879 .div_exact => try sema.zirArithmetic(block, inst, .div_exact),
880 .div_floor => try sema.zirArithmetic(block, inst, .div_floor),
881 .div_trunc => try sema.zirArithmetic(block, inst, .div_trunc),
882878 .mod_rem => try sema.zirArithmetic(block, inst, .mod_rem),
883879 .mod => try sema.zirArithmetic(block, inst, .mod),
884880 .rem => try sema.zirArithmetic(block, inst, .rem),
......@@ -889,6 +885,11 @@ fn analyzeBodyInner(
889885 .subwrap => try sema.zirArithmetic(block, inst, .subwrap),
890886 .sub_sat => try sema.zirArithmetic(block, inst, .sub_sat),
891887
888 .div => try sema.zirDiv(block, inst),
889 .div_exact => try sema.zirDivExact(block, inst),
890 .div_floor => try sema.zirDivFloor(block, inst),
891 .div_trunc => try sema.zirDivTrunc(block, inst),
892
892893 .maximum => try sema.zirMinMax(block, inst, .max),
893894 .minimum => try sema.zirMinMax(block, inst, .min),
894895
......@@ -1146,6 +1147,24 @@ fn analyzeBodyInner(
11461147 i += 1;
11471148 continue;
11481149 },
1150 .check_comptime_control_flow => {
1151 if (!block.is_comptime) {
1152 if (block.runtime_cond orelse block.runtime_loop) |runtime_src| {
1153 const inst_data = sema.code.instructions.items(.data)[inst].node;
1154 const src = LazySrcLoc.nodeOffset(inst_data);
1155 const msg = msg: {
1156 const msg = try sema.errMsg(block, src, "comptime control flow inside runtime block", .{});
1157 errdefer msg.destroy(sema.gpa);
1158
1159 try sema.errNote(block, runtime_src, msg, "runtime control flow here", .{});
1160 break :msg msg;
1161 };
1162 return sema.failWithOwnedErrorMsg(block, msg);
1163 }
1164 }
1165 i += 1;
1166 continue;
1167 },
11491168
11501169 // Special case instructions to handle comptime control flow.
11511170 .@"break" => {
......@@ -3475,19 +3494,43 @@ fn validateArrayInitTy(
34753494 block: *Block,
34763495 inst: Zir.Inst.Index,
34773496) CompileError!void {
3478 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3497 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
34793498 const src = inst_data.src();
3480 const ty = try sema.resolveType(block, src, inst_data.operand);
3499 const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node };
3500 const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;
3501 const ty = try sema.resolveType(block, ty_src, extra.ty);
34813502
34823503 switch (ty.zigTypeTag()) {
3483 .Array, .Vector => return,
3504 .Array => {
3505 const array_len = ty.arrayLen();
3506 if (extra.init_count != array_len) {
3507 return sema.fail(block, src, "expected {d} array elements; found {d}", .{
3508 array_len, extra.init_count,
3509 });
3510 }
3511 return;
3512 },
3513 .Vector => {
3514 const array_len = ty.arrayLen();
3515 if (extra.init_count != array_len) {
3516 return sema.fail(block, src, "expected {d} vector elements; found {d}", .{
3517 array_len, extra.init_count,
3518 });
3519 }
3520 return;
3521 },
34843522 .Struct => if (ty.isTuple()) {
3485 // TODO validate element count
3523 const array_len = ty.arrayLen();
3524 if (extra.init_count > array_len) {
3525 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{
3526 array_len, extra.init_count,
3527 });
3528 }
34863529 return;
34873530 },
34883531 else => {},
34893532 }
3490 return sema.failWithArrayInitNotSupported(block, src, ty);
3533 return sema.failWithArrayInitNotSupported(block, ty_src, ty);
34913534}
34923535
34933536fn validateStructInitTy(
......@@ -3723,6 +3766,15 @@ fn validateStructInit(
37233766
37243767 const default_val = struct_ty.structFieldDefaultValue(i);
37253768 if (default_val.tag() == .unreachable_value) {
3769 if (struct_ty.isTuple()) {
3770 const template = "missing tuple field with index {d}";
3771 if (root_msg) |msg| {
3772 try sema.errNote(block, init_src, msg, template, .{i});
3773 } else {
3774 root_msg = try sema.errMsg(block, init_src, template, .{i});
3775 }
3776 continue;
3777 }
37263778 const field_name = struct_ty.structFieldName(i);
37273779 const template = "missing struct field: {s}";
37283780 const args = .{field_name};
......@@ -3735,7 +3787,10 @@ fn validateStructInit(
37353787 }
37363788
37373789 const field_src = init_src; // TODO better source location
3738 const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
3790 const default_field_ptr = if (struct_ty.isTuple())
3791 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)
3792 else
3793 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
37393794 const field_ty = sema.typeOf(default_field_ptr).childType();
37403795 const init = try sema.addConstant(field_ty, default_val);
37413796 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
......@@ -3850,6 +3905,15 @@ fn validateStructInit(
38503905
38513906 const default_val = struct_ty.structFieldDefaultValue(i);
38523907 if (default_val.tag() == .unreachable_value) {
3908 if (struct_ty.isTuple()) {
3909 const template = "missing tuple field with index {d}";
3910 if (root_msg) |msg| {
3911 try sema.errNote(block, init_src, msg, template, .{i});
3912 } else {
3913 root_msg = try sema.errMsg(block, init_src, template, .{i});
3914 }
3915 continue;
3916 }
38533917 const field_name = struct_ty.structFieldName(i);
38543918 const template = "missing struct field: {s}";
38553919 const args = .{field_name};
......@@ -3893,7 +3957,10 @@ fn validateStructInit(
38933957 if (field_ptr != 0) continue;
38943958
38953959 const field_src = init_src; // TODO better source location
3896 const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
3960 const default_field_ptr = if (struct_ty.isTuple())
3961 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)
3962 else
3963 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
38973964 const field_ty = sema.typeOf(default_field_ptr).childType();
38983965 const init = try sema.addConstant(field_ty, field_values[i]);
38993966 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
......@@ -3916,15 +3983,24 @@ fn zirValidateArrayInit(
39163983 const array_ty = sema.typeOf(array_ptr).childType();
39173984 const array_len = array_ty.arrayLen();
39183985
3919 if (instrs.len != array_len) {
3920 if (array_ty.zigTypeTag() == .Array) {
3921 return sema.fail(block, init_src, "expected {d} array elements; found {d}", .{
3922 array_len, instrs.len,
3923 });
3924 } else {
3925 return sema.fail(block, init_src, "expected {d} vector elements; found {d}", .{
3926 array_len, instrs.len,
3927 });
3986 if (instrs.len != array_len and array_ty.isTuple()) {
3987 const struct_obj = array_ty.castTag(.tuple).?.data;
3988 var root_msg: ?*Module.ErrorMsg = null;
3989 for (struct_obj.values) |default_val, i| {
3990 if (i < instrs.len) continue;
3991
3992 if (default_val.tag() == .unreachable_value) {
3993 const template = "missing tuple field with index {d}";
3994 if (root_msg) |msg| {
3995 try sema.errNote(block, init_src, msg, template, .{i});
3996 } else {
3997 root_msg = try sema.errMsg(block, init_src, template, .{i});
3998 }
3999 }
4000 }
4001
4002 if (root_msg) |msg| {
4003 return sema.failWithOwnedErrorMsg(block, msg);
39284004 }
39294005 }
39304006
......@@ -3977,10 +4053,17 @@ fn zirValidateArrayInit(
39774053 }
39784054 first_block_index = @minimum(first_block_index, block_index);
39794055
3980 // Array has one possible value, so value is always comptime-known
3981 if (opt_opv) |opv| {
3982 element_vals[i] = opv;
3983 continue;
4056 if (array_ty.isTuple()) {
4057 if (array_ty.structFieldValueComptime(i)) |opv| {
4058 element_vals[i] = opv;
4059 continue;
4060 }
4061 } else {
4062 // Array has one possible value, so value is always comptime-known
4063 if (opt_opv) |opv| {
4064 element_vals[i] = opv;
4065 continue;
4066 }
39844067 }
39854068
39864069 // If the next instructon is a store with a comptime operand, this element
......@@ -4674,10 +4757,6 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
46744757 error.OutOfMemory => return error.OutOfMemory,
46754758 else => unreachable, // we pass null for root_src_dir_path
46764759 };
4677 const std_pkg = mod.main_pkg.table.get("std").?;
4678 const builtin_pkg = mod.main_pkg.table.get("builtin").?;
4679 try c_import_pkg.add(sema.gpa, "builtin", builtin_pkg);
4680 try c_import_pkg.add(sema.gpa, "std", std_pkg);
46814760
46824761 const result = mod.importPkg(c_import_pkg) catch |err|
46834762 return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});
......@@ -10842,177 +10921,807 @@ fn zirArithmetic(
1084210921 return sema.analyzeArithmetic(block, zir_tag, lhs, rhs, sema.src, lhs_src, rhs_src);
1084310922}
1084410923
10845fn zirOverflowArithmetic(
10846 sema: *Sema,
10847 block: *Block,
10848 extended: Zir.Inst.Extended.InstData,
10849 zir_tag: Zir.Inst.Extended,
10850) CompileError!Air.Inst.Ref {
10851 const tracy = trace(@src());
10852 defer tracy.end();
10853
10854 const extra = sema.code.extraData(Zir.Inst.OverflowArithmetic, extended.operand).data;
10855 const src = LazySrcLoc.nodeOffset(extra.node);
10856
10857 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
10858 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
10859 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = extra.node };
10860
10924fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
10925 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
10926 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
10927 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
10928 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
10929 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1086110930 const lhs = try sema.resolveInst(extra.lhs);
1086210931 const rhs = try sema.resolveInst(extra.rhs);
10863 const ptr = try sema.resolveInst(extra.ptr);
10864
1086510932 const lhs_ty = sema.typeOf(lhs);
1086610933 const rhs_ty = sema.typeOf(rhs);
10867 const mod = sema.mod;
10868 const target = mod.getTarget();
10869
10870 // Note, the types of lhs/rhs (also for shifting)/ptr are already correct as ensured by astgen.
10934 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
10935 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
1087110936 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
10872 const dest_ty = lhs_ty;
10873 if (dest_ty.scalarType().zigTypeTag() != .Int) {
10874 return sema.fail(block, src, "expected vector of integers or integer tag type, found '{}'", .{dest_ty.fmt(mod)});
10875 }
10937 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div);
1087610938
10877 const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs);
10878 const maybe_rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs);
10939 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
10940 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
10941 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
10942 });
1087910943
10880 const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty);
10881 const ov_ty = tuple_ty.tupleFields().types[1];
10882 // TODO: Remove and use `ov_ty` instead.
10883 // This is a temporary type used until overflow arithmetic properly returns `u1` instead of `bool`.
10884 const overflowed_ty = if (dest_ty.zigTypeTag() == .Vector) try Type.vector(sema.arena, dest_ty.vectorLen(), Type.@"bool") else Type.@"bool";
10944 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
10945 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1088510946
10886 const result: struct {
10887 /// TODO: Rename to `overflow_bit` and make of type `u1`.
10888 overflowed: Air.Inst.Ref,
10889 wrapped: Air.Inst.Ref,
10890 } = result: {
10891 switch (zir_tag) {
10892 .add_with_overflow => {
10893 // If either of the arguments is zero, `false` is returned and the other is stored
10894 // to the result, even if it is undefined..
10895 // Otherwise, if either of the argument is undefined, undefined is returned.
10896 if (maybe_lhs_val) |lhs_val| {
10897 if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
10898 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
10899 }
10900 }
10901 if (maybe_rhs_val) |rhs_val| {
10902 if (!rhs_val.isUndef() and (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
10903 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
10904 }
10905 }
10906 if (maybe_lhs_val) |lhs_val| {
10907 if (maybe_rhs_val) |rhs_val| {
10908 if (lhs_val.isUndef() or rhs_val.isUndef()) {
10909 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
10910 }
10947 const lhs_scalar_ty = lhs_ty.scalarType();
10948 const rhs_scalar_ty = rhs_ty.scalarType();
10949 const scalar_tag = resolved_type.scalarType().zigTypeTag();
1091110950
10912 const result = try sema.intAddWithOverflow(block, src, lhs_val, rhs_val, dest_ty);
10913 const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
10914 const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
10915 break :result .{ .overflowed = overflowed, .wrapped = wrapped };
10916 }
10917 }
10918 },
10919 .sub_with_overflow => {
10920 // If the rhs is zero, then the result is lhs and no overflow occured.
10921 // Otherwise, if either result is undefined, both results are undefined.
10922 if (maybe_rhs_val) |rhs_val| {
10923 if (rhs_val.isUndef()) {
10924 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
10925 } else if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
10926 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
10927 } else if (maybe_lhs_val) |lhs_val| {
10928 if (lhs_val.isUndef()) {
10929 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
10930 }
10951 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1093110952
10932 const result = try sema.intSubWithOverflow(block, src, lhs_val, rhs_val, dest_ty);
10933 const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
10934 const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
10935 break :result .{ .overflowed = overflowed, .wrapped = wrapped };
10953 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div);
10954
10955 const mod = sema.mod;
10956 const target = mod.getTarget();
10957 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(block, lhs_src, casted_lhs);
10958 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(block, rhs_src, casted_rhs);
10959
10960 // TODO: emit compile error when .div is used on integers and there would be an
10961 // ambiguous result between div_floor and div_trunc.
10962
10963 // For integers:
10964 // If the lhs is zero, then zero is returned regardless of rhs.
10965 // If the rhs is zero, compile error for division by zero.
10966 // If the rhs is undefined, compile error because there is a possible
10967 // value (zero) for which the division would be illegal behavior.
10968 // If the lhs is undefined:
10969 // * if lhs type is signed:
10970 // * if rhs is comptime-known and not -1, result is undefined
10971 // * if rhs is -1 or runtime-known, compile error because there is a
10972 // possible value (-min_int / -1) for which division would be
10973 // illegal behavior.
10974 // * if lhs type is unsigned, undef is returned regardless of rhs.
10975 //
10976 // For floats:
10977 // If the rhs is zero:
10978 // * comptime_float: compile error for division by zero.
10979 // * other float type:
10980 // * if the lhs is zero: QNaN
10981 // * otherwise: +Inf or -Inf depending on lhs sign
10982 // If the rhs is undefined:
10983 // * comptime_float: compile error because there is a possible
10984 // value (zero) for which the division would be illegal behavior.
10985 // * other float type: result is undefined
10986 // If the lhs is undefined, result is undefined.
10987 switch (scalar_tag) {
10988 .Int, .ComptimeInt, .ComptimeFloat => {
10989 if (maybe_lhs_val) |lhs_val| {
10990 if (!lhs_val.isUndef()) {
10991 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
10992 return sema.addConstant(resolved_type, Value.zero);
1093610993 }
1093710994 }
10938 },
10939 .mul_with_overflow => {
10940 // If either of the arguments is zero, the result is zero and no overflow occured.
10941 // If either of the arguments is one, the result is the other and no overflow occured.
10942 // Otherwise, if either of the arguments is undefined, both results are undefined.
10943 if (maybe_lhs_val) |lhs_val| {
10944 if (!lhs_val.isUndef()) {
10945 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
10946 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
10947 } else if (try sema.compare(block, src, lhs_val, .eq, Value.one, dest_ty)) {
10948 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
10949 }
10950 }
10995 }
10996 if (maybe_rhs_val) |rhs_val| {
10997 if (rhs_val.isUndef()) {
10998 return sema.failWithUseOfUndef(block, rhs_src);
1095110999 }
10952
10953 if (maybe_rhs_val) |rhs_val| {
10954 if (!rhs_val.isUndef()) {
10955 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
10956 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
10957 } else if (try sema.compare(block, src, rhs_val, .eq, Value.one, dest_ty)) {
10958 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
10959 }
10960 }
11000 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11001 return sema.failWithDivideByZero(block, rhs_src);
1096111002 }
11003 // TODO: if the RHS is one, return the LHS directly
11004 }
11005 },
11006 else => {},
11007 }
1096211008
10963 if (maybe_lhs_val) |lhs_val| {
11009 const runtime_src = rs: {
11010 if (maybe_lhs_val) |lhs_val| {
11011 if (lhs_val.isUndef()) {
11012 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
1096411013 if (maybe_rhs_val) |rhs_val| {
10965 if (lhs_val.isUndef() or rhs_val.isUndef()) {
10966 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
11014 if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
11015 return sema.addConstUndef(resolved_type);
1096711016 }
10968
10969 const result = try lhs_val.intMulWithOverflow(rhs_val, dest_ty, sema.arena, target);
10970 const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
10971 const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
10972 break :result .{ .overflowed = overflowed, .wrapped = wrapped };
10973 }
10974 }
10975 },
10976 .shl_with_overflow => {
10977 // If lhs is zero, the result is zero and no overflow occurred.
10978 // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred.
10979 // Oterhwise if either of the arguments is undefined, both results are undefined.
10980 if (maybe_lhs_val) |lhs_val| {
10981 if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
10982 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
1098311017 }
11018 return sema.failWithUseOfUndef(block, rhs_src);
1098411019 }
10985 if (maybe_rhs_val) |rhs_val| {
10986 if (!rhs_val.isUndef() and (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
10987 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
10988 }
10989 }
10990 if (maybe_lhs_val) |lhs_val| {
10991 if (maybe_rhs_val) |rhs_val| {
10992 if (lhs_val.isUndef() or rhs_val.isUndef()) {
10993 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
10994 }
11020 return sema.addConstUndef(resolved_type);
11021 }
1099511022
10996 const result = try lhs_val.shlWithOverflow(rhs_val, dest_ty, sema.arena, target);
10997 const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
10998 const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
10999 break :result .{ .overflowed = overflowed, .wrapped = wrapped };
11000 }
11023 if (maybe_rhs_val) |rhs_val| {
11024 if (is_int) {
11025 return sema.addConstant(
11026 resolved_type,
11027 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target),
11028 );
11029 } else {
11030 return sema.addConstant(
11031 resolved_type,
11032 try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
11033 );
1100111034 }
11002 },
11003 else => unreachable,
11035 } else {
11036 break :rs rhs_src;
11037 }
11038 } else {
11039 break :rs lhs_src;
1100411040 }
11041 };
1100511042
11006 const air_tag: Air.Inst.Tag = switch (zir_tag) {
11007 .add_with_overflow => .add_with_overflow,
11008 .mul_with_overflow => .mul_with_overflow,
11009 .sub_with_overflow => .sub_with_overflow,
11010 .shl_with_overflow => .shl_with_overflow,
11011 else => unreachable,
11012 };
11013
11014 const runtime_src = if (maybe_lhs_val == null) lhs_src else rhs_src;
11015 try sema.requireRuntimeBlock(block, src, runtime_src);
11043 try sema.requireRuntimeBlock(block, src, runtime_src);
11044
11045 if (block.wantSafety()) {
11046 try sema.addDivIntOverflowSafety(block, resolved_type, lhs_scalar_ty, maybe_lhs_val, maybe_rhs_val, casted_lhs, casted_rhs, is_int);
11047 try sema.addDivByZeroSafety(block, resolved_type, maybe_rhs_val, casted_rhs, is_int);
11048 }
11049
11050 const air_tag = if (is_int) Air.Inst.Tag.div_trunc else switch (block.float_mode) {
11051 .Optimized => Air.Inst.Tag.div_float_optimized,
11052 .Strict => Air.Inst.Tag.div_float,
11053 };
11054 return block.addBinOp(air_tag, casted_lhs, casted_rhs);
11055}
11056
11057fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
11058 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
11059 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
11060 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
11061 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
11062 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
11063 const lhs = try sema.resolveInst(extra.lhs);
11064 const rhs = try sema.resolveInst(extra.rhs);
11065 const lhs_ty = sema.typeOf(lhs);
11066 const rhs_ty = sema.typeOf(rhs);
11067 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
11068 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
11069 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
11070 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div_exact);
11071
11072 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
11073 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
11074 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
11075 });
11076
11077 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
11078 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
11079
11080 const lhs_scalar_ty = lhs_ty.scalarType();
11081 const scalar_tag = resolved_type.scalarType().zigTypeTag();
11082
11083 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
11084
11085 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_exact);
11086
11087 const mod = sema.mod;
11088 const target = mod.getTarget();
11089 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(block, lhs_src, casted_lhs);
11090 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(block, rhs_src, casted_rhs);
11091
11092 const runtime_src = rs: {
11093 // For integers:
11094 // If the lhs is zero, then zero is returned regardless of rhs.
11095 // If the rhs is zero, compile error for division by zero.
11096 // If the rhs is undefined, compile error because there is a possible
11097 // value (zero) for which the division would be illegal behavior.
11098 // If the lhs is undefined, compile error because there is a possible
11099 // value for which the division would result in a remainder.
11100 // TODO: emit runtime safety for if there is a remainder
11101 // TODO: emit runtime safety for division by zero
11102 //
11103 // For floats:
11104 // If the rhs is zero, compile error for division by zero.
11105 // If the rhs is undefined, compile error because there is a possible
11106 // value (zero) for which the division would be illegal behavior.
11107 // If the lhs is undefined, compile error because there is a possible
11108 // value for which the division would result in a remainder.
11109 if (maybe_lhs_val) |lhs_val| {
11110 if (lhs_val.isUndef()) {
11111 return sema.failWithUseOfUndef(block, rhs_src);
11112 } else {
11113 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11114 return sema.addConstant(resolved_type, Value.zero);
11115 }
11116 }
11117 }
11118 if (maybe_rhs_val) |rhs_val| {
11119 if (rhs_val.isUndef()) {
11120 return sema.failWithUseOfUndef(block, rhs_src);
11121 }
11122 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11123 return sema.failWithDivideByZero(block, rhs_src);
11124 }
11125 // TODO: if the RHS is one, return the LHS directly
11126 }
11127 if (maybe_lhs_val) |lhs_val| {
11128 if (maybe_rhs_val) |rhs_val| {
11129 if (is_int) {
11130 // TODO: emit compile error if there is a remainder
11131 return sema.addConstant(
11132 resolved_type,
11133 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target),
11134 );
11135 } else {
11136 // TODO: emit compile error if there is a remainder
11137 return sema.addConstant(
11138 resolved_type,
11139 try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
11140 );
11141 }
11142 } else break :rs rhs_src;
11143 } else break :rs lhs_src;
11144 };
11145
11146 try sema.requireRuntimeBlock(block, src, runtime_src);
11147
11148 // Depending on whether safety is enabled, we will have a slightly different strategy
11149 // here. The `div_exact` AIR instruction causes undefined behavior if a remainder
11150 // is produced, so in the safety check case, it cannot be used. Instead we do a
11151 // div_trunc and check for remainder.
11152
11153 if (block.wantSafety()) {
11154 try sema.addDivIntOverflowSafety(block, resolved_type, lhs_scalar_ty, maybe_lhs_val, maybe_rhs_val, casted_lhs, casted_rhs, is_int);
11155 try sema.addDivByZeroSafety(block, resolved_type, maybe_rhs_val, casted_rhs, is_int);
11156
11157 const result = try block.addBinOp(.div_trunc, casted_lhs, casted_rhs);
11158 const ok = if (!is_int) ok: {
11159 const floored = try block.addUnOp(.floor, result);
11160
11161 if (resolved_type.zigTypeTag() == .Vector) {
11162 const eql = try block.addCmpVector(result, floored, .eq, try sema.addType(resolved_type));
11163 break :ok try block.addInst(.{
11164 .tag = switch (block.float_mode) {
11165 .Strict => .reduce,
11166 .Optimized => .reduce_optimized,
11167 },
11168 .data = .{ .reduce = .{
11169 .operand = eql,
11170 .operation = .And,
11171 } },
11172 });
11173 } else {
11174 const is_in_range = try block.addBinOp(switch (block.float_mode) {
11175 .Strict => .cmp_eq,
11176 .Optimized => .cmp_eq_optimized,
11177 }, result, floored);
11178 break :ok is_in_range;
11179 }
11180 } else ok: {
11181 const remainder = try block.addBinOp(.rem, casted_lhs, casted_rhs);
11182
11183 if (resolved_type.zigTypeTag() == .Vector) {
11184 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
11185 const zero = try sema.addConstant(resolved_type, zero_val);
11186 const eql = try block.addCmpVector(remainder, zero, .eq, try sema.addType(resolved_type));
11187 break :ok try block.addInst(.{
11188 .tag = .reduce,
11189 .data = .{ .reduce = .{
11190 .operand = eql,
11191 .operation = .And,
11192 } },
11193 });
11194 } else {
11195 const zero = try sema.addConstant(resolved_type, Value.zero);
11196 const is_in_range = try block.addBinOp(.cmp_eq, remainder, zero);
11197 break :ok is_in_range;
11198 }
11199 };
11200 try sema.addSafetyCheck(block, ok, .exact_division_remainder);
11201 return result;
11202 }
11203
11204 return block.addBinOp(airTag(block, is_int, .div_exact, .div_exact_optimized), casted_lhs, casted_rhs);
11205}
11206
11207fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
11208 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
11209 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
11210 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
11211 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
11212 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
11213 const lhs = try sema.resolveInst(extra.lhs);
11214 const rhs = try sema.resolveInst(extra.rhs);
11215 const lhs_ty = sema.typeOf(lhs);
11216 const rhs_ty = sema.typeOf(rhs);
11217 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
11218 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
11219 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
11220 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div_floor);
11221
11222 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
11223 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
11224 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
11225 });
11226
11227 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
11228 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
11229
11230 const lhs_scalar_ty = lhs_ty.scalarType();
11231 const rhs_scalar_ty = rhs_ty.scalarType();
11232 const scalar_tag = resolved_type.scalarType().zigTypeTag();
11233
11234 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
11235
11236 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_floor);
11237
11238 const mod = sema.mod;
11239 const target = mod.getTarget();
11240 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(block, lhs_src, casted_lhs);
11241 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(block, rhs_src, casted_rhs);
11242
11243 const runtime_src = rs: {
11244 // For integers:
11245 // If the lhs is zero, then zero is returned regardless of rhs.
11246 // If the rhs is zero, compile error for division by zero.
11247 // If the rhs is undefined, compile error because there is a possible
11248 // value (zero) for which the division would be illegal behavior.
11249 // If the lhs is undefined:
11250 // * if lhs type is signed:
11251 // * if rhs is comptime-known and not -1, result is undefined
11252 // * if rhs is -1 or runtime-known, compile error because there is a
11253 // possible value (-min_int / -1) for which division would be
11254 // illegal behavior.
11255 // * if lhs type is unsigned, undef is returned regardless of rhs.
11256 // TODO: emit runtime safety for division by zero
11257 //
11258 // For floats:
11259 // If the rhs is zero, compile error for division by zero.
11260 // If the rhs is undefined, compile error because there is a possible
11261 // value (zero) for which the division would be illegal behavior.
11262 // If the lhs is undefined, result is undefined.
11263 if (maybe_lhs_val) |lhs_val| {
11264 if (!lhs_val.isUndef()) {
11265 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11266 return sema.addConstant(resolved_type, Value.zero);
11267 }
11268 }
11269 }
11270 if (maybe_rhs_val) |rhs_val| {
11271 if (rhs_val.isUndef()) {
11272 return sema.failWithUseOfUndef(block, rhs_src);
11273 }
11274 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11275 return sema.failWithDivideByZero(block, rhs_src);
11276 }
11277 // TODO: if the RHS is one, return the LHS directly
11278 }
11279 if (maybe_lhs_val) |lhs_val| {
11280 if (lhs_val.isUndef()) {
11281 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
11282 if (maybe_rhs_val) |rhs_val| {
11283 if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
11284 return sema.addConstUndef(resolved_type);
11285 }
11286 }
11287 return sema.failWithUseOfUndef(block, rhs_src);
11288 }
11289 return sema.addConstUndef(resolved_type);
11290 }
11291
11292 if (maybe_rhs_val) |rhs_val| {
11293 if (is_int) {
11294 return sema.addConstant(
11295 resolved_type,
11296 try lhs_val.intDivFloor(rhs_val, resolved_type, sema.arena, target),
11297 );
11298 } else {
11299 return sema.addConstant(
11300 resolved_type,
11301 try lhs_val.floatDivFloor(rhs_val, resolved_type, sema.arena, target),
11302 );
11303 }
11304 } else break :rs rhs_src;
11305 } else break :rs lhs_src;
11306 };
11307
11308 try sema.requireRuntimeBlock(block, src, runtime_src);
11309
11310 if (block.wantSafety()) {
11311 try sema.addDivIntOverflowSafety(block, resolved_type, lhs_scalar_ty, maybe_lhs_val, maybe_rhs_val, casted_lhs, casted_rhs, is_int);
11312 try sema.addDivByZeroSafety(block, resolved_type, maybe_rhs_val, casted_rhs, is_int);
11313 }
11314
11315 return block.addBinOp(airTag(block, is_int, .div_floor, .div_floor_optimized), casted_lhs, casted_rhs);
11316}
11317
11318fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
11319 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
11320 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
11321 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
11322 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
11323 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
11324 const lhs = try sema.resolveInst(extra.lhs);
11325 const rhs = try sema.resolveInst(extra.rhs);
11326 const lhs_ty = sema.typeOf(lhs);
11327 const rhs_ty = sema.typeOf(rhs);
11328 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
11329 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
11330 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
11331 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div_trunc);
11332
11333 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
11334 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
11335 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
11336 });
11337
11338 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
11339 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
11340
11341 const lhs_scalar_ty = lhs_ty.scalarType();
11342 const rhs_scalar_ty = rhs_ty.scalarType();
11343 const scalar_tag = resolved_type.scalarType().zigTypeTag();
11344
11345 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
11346
11347 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_trunc);
11348
11349 const mod = sema.mod;
11350 const target = mod.getTarget();
11351 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(block, lhs_src, casted_lhs);
11352 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(block, rhs_src, casted_rhs);
11353
11354 const runtime_src = rs: {
11355 // For integers:
11356 // If the lhs is zero, then zero is returned regardless of rhs.
11357 // If the rhs is zero, compile error for division by zero.
11358 // If the rhs is undefined, compile error because there is a possible
11359 // value (zero) for which the division would be illegal behavior.
11360 // If the lhs is undefined:
11361 // * if lhs type is signed:
11362 // * if rhs is comptime-known and not -1, result is undefined
11363 // * if rhs is -1 or runtime-known, compile error because there is a
11364 // possible value (-min_int / -1) for which division would be
11365 // illegal behavior.
11366 // * if lhs type is unsigned, undef is returned regardless of rhs.
11367 // TODO: emit runtime safety for division by zero
11368 //
11369 // For floats:
11370 // If the rhs is zero, compile error for division by zero.
11371 // If the rhs is undefined, compile error because there is a possible
11372 // value (zero) for which the division would be illegal behavior.
11373 // If the lhs is undefined, result is undefined.
11374 if (maybe_lhs_val) |lhs_val| {
11375 if (!lhs_val.isUndef()) {
11376 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11377 return sema.addConstant(resolved_type, Value.zero);
11378 }
11379 }
11380 }
11381 if (maybe_rhs_val) |rhs_val| {
11382 if (rhs_val.isUndef()) {
11383 return sema.failWithUseOfUndef(block, rhs_src);
11384 }
11385 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11386 return sema.failWithDivideByZero(block, rhs_src);
11387 }
11388 }
11389 if (maybe_lhs_val) |lhs_val| {
11390 if (lhs_val.isUndef()) {
11391 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
11392 if (maybe_rhs_val) |rhs_val| {
11393 if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
11394 return sema.addConstUndef(resolved_type);
11395 }
11396 }
11397 return sema.failWithUseOfUndef(block, rhs_src);
11398 }
11399 return sema.addConstUndef(resolved_type);
11400 }
11401
11402 if (maybe_rhs_val) |rhs_val| {
11403 if (is_int) {
11404 return sema.addConstant(
11405 resolved_type,
11406 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target),
11407 );
11408 } else {
11409 return sema.addConstant(
11410 resolved_type,
11411 try lhs_val.floatDivTrunc(rhs_val, resolved_type, sema.arena, target),
11412 );
11413 }
11414 } else break :rs rhs_src;
11415 } else break :rs lhs_src;
11416 };
11417
11418 try sema.requireRuntimeBlock(block, src, runtime_src);
11419
11420 if (block.wantSafety()) {
11421 try sema.addDivIntOverflowSafety(block, resolved_type, lhs_scalar_ty, maybe_lhs_val, maybe_rhs_val, casted_lhs, casted_rhs, is_int);
11422 try sema.addDivByZeroSafety(block, resolved_type, maybe_rhs_val, casted_rhs, is_int);
11423 }
11424
11425 return block.addBinOp(airTag(block, is_int, .div_trunc, .div_trunc_optimized), casted_lhs, casted_rhs);
11426}
11427
11428fn addDivIntOverflowSafety(
11429 sema: *Sema,
11430 block: *Block,
11431 resolved_type: Type,
11432 lhs_scalar_ty: Type,
11433 maybe_lhs_val: ?Value,
11434 maybe_rhs_val: ?Value,
11435 casted_lhs: Air.Inst.Ref,
11436 casted_rhs: Air.Inst.Ref,
11437 is_int: bool,
11438) CompileError!void {
11439 if (!is_int) return;
11440
11441 // If the LHS is unsigned, it cannot cause overflow.
11442 if (!lhs_scalar_ty.isSignedInt()) return;
11443
11444 const mod = sema.mod;
11445 const target = mod.getTarget();
11446
11447 // If the LHS is widened to a larger integer type, no overflow is possible.
11448 if (lhs_scalar_ty.intInfo(target).bits < resolved_type.intInfo(target).bits) {
11449 return;
11450 }
11451
11452 const min_int = try resolved_type.minInt(sema.arena, target);
11453 const neg_one_scalar = try Value.Tag.int_i64.create(sema.arena, -1);
11454 const neg_one = if (resolved_type.zigTypeTag() == .Vector)
11455 try Value.Tag.repeated.create(sema.arena, neg_one_scalar)
11456 else
11457 neg_one_scalar;
11458
11459 // If the LHS is comptime-known to be not equal to the min int,
11460 // no overflow is possible.
11461 if (maybe_lhs_val) |lhs_val| {
11462 if (!lhs_val.compare(.eq, min_int, resolved_type, mod)) return;
11463 }
11464
11465 // If the RHS is comptime-known to not be equal to -1, no overflow is possible.
11466 if (maybe_rhs_val) |rhs_val| {
11467 if (!rhs_val.compare(.eq, neg_one, resolved_type, mod)) return;
11468 }
11469
11470 var ok: Air.Inst.Ref = .none;
11471 if (resolved_type.zigTypeTag() == .Vector) {
11472 const vector_ty_ref = try sema.addType(resolved_type);
11473 if (maybe_lhs_val == null) {
11474 const min_int_ref = try sema.addConstant(resolved_type, min_int);
11475 ok = try block.addCmpVector(casted_lhs, min_int_ref, .neq, vector_ty_ref);
11476 }
11477 if (maybe_rhs_val == null) {
11478 const neg_one_ref = try sema.addConstant(resolved_type, neg_one);
11479 const rhs_ok = try block.addCmpVector(casted_rhs, neg_one_ref, .neq, vector_ty_ref);
11480 if (ok == .none) {
11481 ok = rhs_ok;
11482 } else {
11483 ok = try block.addBinOp(.bool_or, ok, rhs_ok);
11484 }
11485 }
11486 assert(ok != .none);
11487 ok = try block.addInst(.{
11488 .tag = .reduce,
11489 .data = .{ .reduce = .{
11490 .operand = ok,
11491 .operation = .And,
11492 } },
11493 });
11494 } else {
11495 if (maybe_lhs_val == null) {
11496 const min_int_ref = try sema.addConstant(resolved_type, min_int);
11497 ok = try block.addBinOp(.cmp_neq, casted_lhs, min_int_ref);
11498 }
11499 if (maybe_rhs_val == null) {
11500 const neg_one_ref = try sema.addConstant(resolved_type, neg_one);
11501 const rhs_ok = try block.addBinOp(.cmp_neq, casted_rhs, neg_one_ref);
11502 if (ok == .none) {
11503 ok = rhs_ok;
11504 } else {
11505 ok = try block.addBinOp(.bool_or, ok, rhs_ok);
11506 }
11507 }
11508 assert(ok != .none);
11509 }
11510 try sema.addSafetyCheck(block, ok, .integer_overflow);
11511}
11512
11513fn addDivByZeroSafety(
11514 sema: *Sema,
11515 block: *Block,
11516 resolved_type: Type,
11517 maybe_rhs_val: ?Value,
11518 casted_rhs: Air.Inst.Ref,
11519 is_int: bool,
11520) CompileError!void {
11521 // Strict IEEE floats have well-defined division by zero.
11522 if (!is_int and block.float_mode == .Strict) return;
11523
11524 // If rhs was comptime-known to be zero a compile error would have been
11525 // emitted above.
11526 if (maybe_rhs_val != null) return;
11527
11528 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
11529 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
11530 const zero = try sema.addConstant(resolved_type, zero_val);
11531 const ok = try block.addCmpVector(casted_rhs, zero, .neq, try sema.addType(resolved_type));
11532 break :ok try block.addInst(.{
11533 .tag = if (is_int) .reduce else .reduce_optimized,
11534 .data = .{ .reduce = .{
11535 .operand = ok,
11536 .operation = .And,
11537 } },
11538 });
11539 } else ok: {
11540 const zero = try sema.addConstant(resolved_type, Value.zero);
11541 break :ok try block.addBinOp(if (is_int) .cmp_neq else .cmp_neq_optimized, casted_rhs, zero);
11542 };
11543 try sema.addSafetyCheck(block, ok, .divide_by_zero);
11544}
11545
11546fn airTag(block: *Block, is_int: bool, normal: Air.Inst.Tag, optimized: Air.Inst.Tag) Air.Inst.Tag {
11547 if (is_int) return normal;
11548 return switch (block.float_mode) {
11549 .Strict => normal,
11550 .Optimized => optimized,
11551 };
11552}
11553
11554fn zirOverflowArithmetic(
11555 sema: *Sema,
11556 block: *Block,
11557 extended: Zir.Inst.Extended.InstData,
11558 zir_tag: Zir.Inst.Extended,
11559) CompileError!Air.Inst.Ref {
11560 const tracy = trace(@src());
11561 defer tracy.end();
11562
11563 const extra = sema.code.extraData(Zir.Inst.OverflowArithmetic, extended.operand).data;
11564 const src = LazySrcLoc.nodeOffset(extra.node);
11565
11566 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
11567 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
11568 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = extra.node };
11569
11570 const lhs = try sema.resolveInst(extra.lhs);
11571 const rhs = try sema.resolveInst(extra.rhs);
11572 const ptr = try sema.resolveInst(extra.ptr);
11573
11574 const lhs_ty = sema.typeOf(lhs);
11575 const rhs_ty = sema.typeOf(rhs);
11576 const mod = sema.mod;
11577 const target = mod.getTarget();
11578
11579 // Note, the types of lhs/rhs (also for shifting)/ptr are already correct as ensured by astgen.
11580 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
11581 const dest_ty = lhs_ty;
11582 if (dest_ty.scalarType().zigTypeTag() != .Int) {
11583 return sema.fail(block, src, "expected vector of integers or integer tag type, found '{}'", .{dest_ty.fmt(mod)});
11584 }
11585
11586 const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs);
11587 const maybe_rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, rhs);
11588
11589 const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty);
11590 const ov_ty = tuple_ty.tupleFields().types[1];
11591 // TODO: Remove and use `ov_ty` instead.
11592 // This is a temporary type used until overflow arithmetic properly returns `u1` instead of `bool`.
11593 const overflowed_ty = if (dest_ty.zigTypeTag() == .Vector) try Type.vector(sema.arena, dest_ty.vectorLen(), Type.@"bool") else Type.@"bool";
11594
11595 const result: struct {
11596 /// TODO: Rename to `overflow_bit` and make of type `u1`.
11597 overflowed: Air.Inst.Ref,
11598 wrapped: Air.Inst.Ref,
11599 } = result: {
11600 switch (zir_tag) {
11601 .add_with_overflow => {
11602 // If either of the arguments is zero, `false` is returned and the other is stored
11603 // to the result, even if it is undefined..
11604 // Otherwise, if either of the argument is undefined, undefined is returned.
11605 if (maybe_lhs_val) |lhs_val| {
11606 if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
11607 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
11608 }
11609 }
11610 if (maybe_rhs_val) |rhs_val| {
11611 if (!rhs_val.isUndef() and (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
11612 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
11613 }
11614 }
11615 if (maybe_lhs_val) |lhs_val| {
11616 if (maybe_rhs_val) |rhs_val| {
11617 if (lhs_val.isUndef() or rhs_val.isUndef()) {
11618 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
11619 }
11620
11621 const result = try sema.intAddWithOverflow(block, src, lhs_val, rhs_val, dest_ty);
11622 const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
11623 const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
11624 break :result .{ .overflowed = overflowed, .wrapped = wrapped };
11625 }
11626 }
11627 },
11628 .sub_with_overflow => {
11629 // If the rhs is zero, then the result is lhs and no overflow occured.
11630 // Otherwise, if either result is undefined, both results are undefined.
11631 if (maybe_rhs_val) |rhs_val| {
11632 if (rhs_val.isUndef()) {
11633 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
11634 } else if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11635 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
11636 } else if (maybe_lhs_val) |lhs_val| {
11637 if (lhs_val.isUndef()) {
11638 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
11639 }
11640
11641 const result = try sema.intSubWithOverflow(block, src, lhs_val, rhs_val, dest_ty);
11642 const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
11643 const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
11644 break :result .{ .overflowed = overflowed, .wrapped = wrapped };
11645 }
11646 }
11647 },
11648 .mul_with_overflow => {
11649 // If either of the arguments is zero, the result is zero and no overflow occured.
11650 // If either of the arguments is one, the result is the other and no overflow occured.
11651 // Otherwise, if either of the arguments is undefined, both results are undefined.
11652 if (maybe_lhs_val) |lhs_val| {
11653 if (!lhs_val.isUndef()) {
11654 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11655 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
11656 } else if (try sema.compare(block, src, lhs_val, .eq, Value.one, dest_ty)) {
11657 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
11658 }
11659 }
11660 }
11661
11662 if (maybe_rhs_val) |rhs_val| {
11663 if (!rhs_val.isUndef()) {
11664 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11665 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
11666 } else if (try sema.compare(block, src, rhs_val, .eq, Value.one, dest_ty)) {
11667 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
11668 }
11669 }
11670 }
11671
11672 if (maybe_lhs_val) |lhs_val| {
11673 if (maybe_rhs_val) |rhs_val| {
11674 if (lhs_val.isUndef() or rhs_val.isUndef()) {
11675 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
11676 }
11677
11678 const result = try lhs_val.intMulWithOverflow(rhs_val, dest_ty, sema.arena, target);
11679 const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
11680 const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
11681 break :result .{ .overflowed = overflowed, .wrapped = wrapped };
11682 }
11683 }
11684 },
11685 .shl_with_overflow => {
11686 // If lhs is zero, the result is zero and no overflow occurred.
11687 // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred.
11688 // Oterhwise if either of the arguments is undefined, both results are undefined.
11689 if (maybe_lhs_val) |lhs_val| {
11690 if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
11691 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
11692 }
11693 }
11694 if (maybe_rhs_val) |rhs_val| {
11695 if (!rhs_val.isUndef() and (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
11696 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
11697 }
11698 }
11699 if (maybe_lhs_val) |lhs_val| {
11700 if (maybe_rhs_val) |rhs_val| {
11701 if (lhs_val.isUndef() or rhs_val.isUndef()) {
11702 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
11703 }
11704
11705 const result = try lhs_val.shlWithOverflow(rhs_val, dest_ty, sema.arena, target);
11706 const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
11707 const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
11708 break :result .{ .overflowed = overflowed, .wrapped = wrapped };
11709 }
11710 }
11711 },
11712 else => unreachable,
11713 }
11714
11715 const air_tag: Air.Inst.Tag = switch (zir_tag) {
11716 .add_with_overflow => .add_with_overflow,
11717 .mul_with_overflow => .mul_with_overflow,
11718 .sub_with_overflow => .sub_with_overflow,
11719 .shl_with_overflow => .shl_with_overflow,
11720 else => unreachable,
11721 };
11722
11723 const runtime_src = if (maybe_lhs_val == null) lhs_src else rhs_src;
11724 try sema.requireRuntimeBlock(block, src, runtime_src);
1101611725
1101711726 const tuple = try block.addInst(.{
1101811727 .tag = air_tag,
......@@ -11108,13 +11817,8 @@ fn analyzeArithmetic(
1110811817 const scalar_tag = resolved_type.scalarType().zigTypeTag();
1110911818
1111011819 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
11111 const is_float = scalar_tag == .Float or scalar_tag == .ComptimeFloat;
1111211820
11113 if (!is_int and !(is_float and floatOpAllowed(zir_tag))) {
11114 return sema.fail(block, src, "invalid operands to binary expression: '{s}' and '{s}'", .{
11115 @tagName(lhs_zig_ty_tag), @tagName(rhs_zig_ty_tag),
11116 });
11117 }
11821 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, zir_tag);
1111811822
1111911823 const mod = sema.mod;
1112011824 const target = mod.getTarget();
......@@ -11321,277 +12025,6 @@ fn analyzeArithmetic(
1132112025 } else break :rs .{ .src = rhs_src, .air_tag = .sub_sat };
1132212026 } else break :rs .{ .src = lhs_src, .air_tag = .sub_sat };
1132312027 },
11324 .div => {
11325 // TODO: emit compile error when .div is used on integers and there would be an
11326 // ambiguous result between div_floor and div_trunc.
11327
11328 // For integers:
11329 // If the lhs is zero, then zero is returned regardless of rhs.
11330 // If the rhs is zero, compile error for division by zero.
11331 // If the rhs is undefined, compile error because there is a possible
11332 // value (zero) for which the division would be illegal behavior.
11333 // If the lhs is undefined:
11334 // * if lhs type is signed:
11335 // * if rhs is comptime-known and not -1, result is undefined
11336 // * if rhs is -1 or runtime-known, compile error because there is a
11337 // possible value (-min_int / -1) for which division would be
11338 // illegal behavior.
11339 // * if lhs type is unsigned, undef is returned regardless of rhs.
11340 // TODO: emit runtime safety for division by zero
11341 //
11342 // For floats:
11343 // If the rhs is zero:
11344 // * comptime_float: compile error for division by zero.
11345 // * other float type:
11346 // * if the lhs is zero: QNaN
11347 // * otherwise: +Inf or -Inf depending on lhs sign
11348 // If the rhs is undefined:
11349 // * comptime_float: compile error because there is a possible
11350 // value (zero) for which the division would be illegal behavior.
11351 // * other float type: result is undefined
11352 // If the lhs is undefined, result is undefined.
11353 switch (scalar_tag) {
11354 .Int, .ComptimeInt, .ComptimeFloat => {
11355 if (maybe_lhs_val) |lhs_val| {
11356 if (!lhs_val.isUndef()) {
11357 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11358 return sema.addConstant(resolved_type, Value.zero);
11359 }
11360 }
11361 }
11362 if (maybe_rhs_val) |rhs_val| {
11363 if (rhs_val.isUndef()) {
11364 return sema.failWithUseOfUndef(block, rhs_src);
11365 }
11366 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11367 return sema.failWithDivideByZero(block, rhs_src);
11368 }
11369 }
11370 },
11371 else => {},
11372 }
11373
11374 if (maybe_lhs_val) |lhs_val| {
11375 if (lhs_val.isUndef()) {
11376 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
11377 if (maybe_rhs_val) |rhs_val| {
11378 if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
11379 return sema.addConstUndef(resolved_type);
11380 }
11381 }
11382 return sema.failWithUseOfUndef(block, rhs_src);
11383 }
11384 return sema.addConstUndef(resolved_type);
11385 }
11386
11387 if (maybe_rhs_val) |rhs_val| {
11388 if (is_int) {
11389 return sema.addConstant(
11390 resolved_type,
11391 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target),
11392 );
11393 } else {
11394 return sema.addConstant(
11395 resolved_type,
11396 try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
11397 );
11398 }
11399 } else {
11400 if (is_int) {
11401 break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
11402 } else {
11403 break :rs .{ .src = rhs_src, .air_tag = if (block.float_mode == .Optimized) .div_float_optimized else .div_float };
11404 }
11405 }
11406 } else {
11407 if (is_int) {
11408 break :rs .{ .src = lhs_src, .air_tag = .div_trunc };
11409 } else {
11410 break :rs .{ .src = lhs_src, .air_tag = if (block.float_mode == .Optimized) .div_float_optimized else .div_float };
11411 }
11412 }
11413 },
11414 .div_trunc => {
11415 // For integers:
11416 // If the lhs is zero, then zero is returned regardless of rhs.
11417 // If the rhs is zero, compile error for division by zero.
11418 // If the rhs is undefined, compile error because there is a possible
11419 // value (zero) for which the division would be illegal behavior.
11420 // If the lhs is undefined:
11421 // * if lhs type is signed:
11422 // * if rhs is comptime-known and not -1, result is undefined
11423 // * if rhs is -1 or runtime-known, compile error because there is a
11424 // possible value (-min_int / -1) for which division would be
11425 // illegal behavior.
11426 // * if lhs type is unsigned, undef is returned regardless of rhs.
11427 // TODO: emit runtime safety for division by zero
11428 //
11429 // For floats:
11430 // If the rhs is zero, compile error for division by zero.
11431 // If the rhs is undefined, compile error because there is a possible
11432 // value (zero) for which the division would be illegal behavior.
11433 // If the lhs is undefined, result is undefined.
11434 if (maybe_lhs_val) |lhs_val| {
11435 if (!lhs_val.isUndef()) {
11436 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11437 return sema.addConstant(resolved_type, Value.zero);
11438 }
11439 }
11440 }
11441 if (maybe_rhs_val) |rhs_val| {
11442 if (rhs_val.isUndef()) {
11443 return sema.failWithUseOfUndef(block, rhs_src);
11444 }
11445 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11446 return sema.failWithDivideByZero(block, rhs_src);
11447 }
11448 }
11449 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_trunc_optimized else .div_trunc;
11450 if (maybe_lhs_val) |lhs_val| {
11451 if (lhs_val.isUndef()) {
11452 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
11453 if (maybe_rhs_val) |rhs_val| {
11454 if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
11455 return sema.addConstUndef(resolved_type);
11456 }
11457 }
11458 return sema.failWithUseOfUndef(block, rhs_src);
11459 }
11460 return sema.addConstUndef(resolved_type);
11461 }
11462
11463 if (maybe_rhs_val) |rhs_val| {
11464 if (is_int) {
11465 return sema.addConstant(
11466 resolved_type,
11467 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target),
11468 );
11469 } else {
11470 return sema.addConstant(
11471 resolved_type,
11472 try lhs_val.floatDivTrunc(rhs_val, resolved_type, sema.arena, target),
11473 );
11474 }
11475 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11476 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11477 },
11478 .div_floor => {
11479 // For integers:
11480 // If the lhs is zero, then zero is returned regardless of rhs.
11481 // If the rhs is zero, compile error for division by zero.
11482 // If the rhs is undefined, compile error because there is a possible
11483 // value (zero) for which the division would be illegal behavior.
11484 // If the lhs is undefined:
11485 // * if lhs type is signed:
11486 // * if rhs is comptime-known and not -1, result is undefined
11487 // * if rhs is -1 or runtime-known, compile error because there is a
11488 // possible value (-min_int / -1) for which division would be
11489 // illegal behavior.
11490 // * if lhs type is unsigned, undef is returned regardless of rhs.
11491 // TODO: emit runtime safety for division by zero
11492 //
11493 // For floats:
11494 // If the rhs is zero, compile error for division by zero.
11495 // If the rhs is undefined, compile error because there is a possible
11496 // value (zero) for which the division would be illegal behavior.
11497 // If the lhs is undefined, result is undefined.
11498 if (maybe_lhs_val) |lhs_val| {
11499 if (!lhs_val.isUndef()) {
11500 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11501 return sema.addConstant(resolved_type, Value.zero);
11502 }
11503 }
11504 }
11505 if (maybe_rhs_val) |rhs_val| {
11506 if (rhs_val.isUndef()) {
11507 return sema.failWithUseOfUndef(block, rhs_src);
11508 }
11509 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11510 return sema.failWithDivideByZero(block, rhs_src);
11511 }
11512 }
11513 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_floor_optimized else .div_floor;
11514 if (maybe_lhs_val) |lhs_val| {
11515 if (lhs_val.isUndef()) {
11516 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
11517 if (maybe_rhs_val) |rhs_val| {
11518 if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
11519 return sema.addConstUndef(resolved_type);
11520 }
11521 }
11522 return sema.failWithUseOfUndef(block, rhs_src);
11523 }
11524 return sema.addConstUndef(resolved_type);
11525 }
11526
11527 if (maybe_rhs_val) |rhs_val| {
11528 if (is_int) {
11529 return sema.addConstant(
11530 resolved_type,
11531 try lhs_val.intDivFloor(rhs_val, resolved_type, sema.arena, target),
11532 );
11533 } else {
11534 return sema.addConstant(
11535 resolved_type,
11536 try lhs_val.floatDivFloor(rhs_val, resolved_type, sema.arena, target),
11537 );
11538 }
11539 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11540 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11541 },
11542 .div_exact => {
11543 // For integers:
11544 // If the lhs is zero, then zero is returned regardless of rhs.
11545 // If the rhs is zero, compile error for division by zero.
11546 // If the rhs is undefined, compile error because there is a possible
11547 // value (zero) for which the division would be illegal behavior.
11548 // If the lhs is undefined, compile error because there is a possible
11549 // value for which the division would result in a remainder.
11550 // TODO: emit runtime safety for if there is a remainder
11551 // TODO: emit runtime safety for division by zero
11552 //
11553 // For floats:
11554 // If the rhs is zero, compile error for division by zero.
11555 // If the rhs is undefined, compile error because there is a possible
11556 // value (zero) for which the division would be illegal behavior.
11557 // If the lhs is undefined, compile error because there is a possible
11558 // value for which the division would result in a remainder.
11559 if (maybe_lhs_val) |lhs_val| {
11560 if (lhs_val.isUndef()) {
11561 return sema.failWithUseOfUndef(block, rhs_src);
11562 } else {
11563 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11564 return sema.addConstant(resolved_type, Value.zero);
11565 }
11566 }
11567 }
11568 if (maybe_rhs_val) |rhs_val| {
11569 if (rhs_val.isUndef()) {
11570 return sema.failWithUseOfUndef(block, rhs_src);
11571 }
11572 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11573 return sema.failWithDivideByZero(block, rhs_src);
11574 }
11575 }
11576 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .div_exact_optimized else .div_exact;
11577 if (maybe_lhs_val) |lhs_val| {
11578 if (maybe_rhs_val) |rhs_val| {
11579 if (is_int) {
11580 // TODO: emit compile error if there is a remainder
11581 return sema.addConstant(
11582 resolved_type,
11583 try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target),
11584 );
11585 } else {
11586 // TODO: emit compile error if there is a remainder
11587 return sema.addConstant(
11588 resolved_type,
11589 try lhs_val.floatDiv(rhs_val, resolved_type, sema.arena, target),
11590 );
11591 }
11592 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
11593 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
11594 },
1159512028 .mul => {
1159612029 // For integers:
1159712030 // If either of the operands are zero, the result is zero.
......@@ -11960,38 +12393,16 @@ fn analyzeArithmetic(
1196012393 .operation = .Or,
1196112394 } },
1196212395 })
11963 else
11964 ov_bit;
11965 const zero_ov = try sema.addConstant(Type.@"u1", Value.zero);
11966 const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);
11967
11968 try sema.addSafetyCheck(block, no_ov, .integer_overflow);
11969 return sema.tupleFieldValByIndex(block, src, op_ov, 0, op_ov_tuple_ty);
11970 }
11971 }
11972 switch (rs.air_tag) {
11973 // zig fmt: off
11974 .div_float, .div_exact, .div_trunc, .div_floor, .div_float_optimized,
11975 .div_exact_optimized, .div_trunc_optimized, .div_floor_optimized
11976 // zig fmt: on
11977 => if (scalar_tag == .Int or block.float_mode == .Optimized) {
11978 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
11979 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
11980 const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);
11981 const ok = try block.addCmpVector(casted_rhs, zero, .neq, try sema.addType(resolved_type));
11982 break :ok try block.addInst(.{
11983 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
11984 .data = .{ .reduce = .{
11985 .operand = ok,
11986 .operation = .And,
11987 } },
11988 });
11989 } else ok: {
11990 const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);
11991 break :ok try block.addBinOp(if (block.float_mode == .Optimized) .cmp_neq_optimized else .cmp_neq, casted_rhs, zero);
11992 };
11993 try sema.addSafetyCheck(block, ok, .divide_by_zero);
11994 },
12396 else
12397 ov_bit;
12398 const zero_ov = try sema.addConstant(Type.@"u1", Value.zero);
12399 const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);
12400
12401 try sema.addSafetyCheck(block, no_ov, .integer_overflow);
12402 return sema.tupleFieldValByIndex(block, src, op_ov, 0, op_ov_tuple_ty);
12403 }
12404 }
12405 switch (rs.air_tag) {
1199512406 .rem, .mod, .rem_optimized, .mod_optimized => {
1199612407 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
1199712408 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
......@@ -12018,47 +12429,6 @@ fn analyzeArithmetic(
1201812429 },
1201912430 else => {},
1202012431 }
12021 if (rs.air_tag == .div_exact or rs.air_tag == .div_exact_optimized) {
12022 const result = try block.addBinOp(.div_exact, casted_lhs, casted_rhs);
12023 const ok = if (scalar_tag == .Float) ok: {
12024 const floored = try block.addUnOp(.floor, result);
12025
12026 if (resolved_type.zigTypeTag() == .Vector) {
12027 const eql = try block.addCmpVector(result, floored, .eq, try sema.addType(resolved_type));
12028 break :ok try block.addInst(.{
12029 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
12030 .data = .{ .reduce = .{
12031 .operand = eql,
12032 .operation = .And,
12033 } },
12034 });
12035 } else {
12036 const is_in_range = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, result, floored);
12037 break :ok is_in_range;
12038 }
12039 } else ok: {
12040 const remainder = try block.addBinOp(.rem, casted_lhs, casted_rhs);
12041
12042 if (resolved_type.zigTypeTag() == .Vector) {
12043 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
12044 const zero = try sema.addConstant(sema.typeOf(casted_rhs), zero_val);
12045 const eql = try block.addCmpVector(remainder, zero, .eq, try sema.addType(resolved_type));
12046 break :ok try block.addInst(.{
12047 .tag = .reduce,
12048 .data = .{ .reduce = .{
12049 .operand = eql,
12050 .operation = .And,
12051 } },
12052 });
12053 } else {
12054 const zero = try sema.addConstant(sema.typeOf(casted_rhs), Value.zero);
12055 const is_in_range = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, remainder, zero);
12056 break :ok is_in_range;
12057 }
12058 };
12059 try sema.addSafetyCheck(block, ok, .exact_division_remainder);
12060 return result;
12061 }
1206212432 }
1206312433 return block.addBinOp(rs.air_tag, casted_lhs, casted_rhs);
1206412434}
......@@ -14696,6 +15066,22 @@ fn finishStructInit(
1469615066 field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val);
1469715067 }
1469815068 }
15069 } else if (struct_ty.isTuple()) {
15070 const struct_obj = struct_ty.castTag(.tuple).?.data;
15071 for (struct_obj.values) |default_val, i| {
15072 if (field_inits[i] != .none) continue;
15073
15074 if (default_val.tag() == .unreachable_value) {
15075 const template = "missing tuple field with index {d}";
15076 if (root_msg) |msg| {
15077 try sema.errNote(block, init_src, msg, template, .{i});
15078 } else {
15079 root_msg = try sema.errMsg(block, init_src, template, .{i});
15080 }
15081 } else {
15082 field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val);
15083 }
15084 }
1469915085 } else {
1470015086 const struct_obj = struct_ty.castTag(.@"struct").?.data;
1470115087 for (struct_obj.fields.values()) |field, i| {
......@@ -15373,6 +15759,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1537315759 const tag_ty = type_info_ty.unionTagType().?;
1537415760 const target = mod.getTarget();
1537515761 const tag_index = tag_ty.enumTagFieldIndex(union_val.tag, mod).?;
15762 if (union_val.val.anyUndef()) return sema.failWithUseOfUndef(block, src);
1537615763 switch (@intToEnum(std.builtin.TypeId, tag_index)) {
1537715764 .Type => return Air.Inst.Ref.type_type,
1537815765 .Void => return Air.Inst.Ref.void_type,
......@@ -15442,7 +15829,10 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1544215829 const is_allowzero_val = struct_val[6];
1544315830 const sentinel_val = struct_val[7];
1544415831
15445 const abi_align = @intCast(u29, alignment_val.toUnsignedInt(target)); // TODO: Validate this value.
15832 if (!try sema.intFitsInType(block, src, alignment_val, Type.u32, null)) {
15833 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
15834 }
15835 const abi_align = @intCast(u29, alignment_val.toUnsignedInt(target));
1544615836
1544715837 var buffer: Value.ToTypeBuffer = undefined;
1544815838 const unresolved_elem_ty = child_val.toType(&buffer);
......@@ -15469,6 +15859,39 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1546915859 actual_sentinel = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?;
1547015860 }
1547115861
15862 if (elem_ty.zigTypeTag() == .NoReturn) {
15863 return sema.fail(block, src, "pointer to noreturn not allowed", .{});
15864 } else if (elem_ty.zigTypeTag() == .Fn) {
15865 if (ptr_size != .One) {
15866 return sema.fail(block, src, "function pointers must be single pointers", .{});
15867 }
15868 const fn_align = elem_ty.fnInfo().alignment;
15869 if (abi_align != 0 and fn_align != 0 and
15870 abi_align != fn_align)
15871 {
15872 return sema.fail(block, src, "function pointer alignment disagrees with function alignment", .{});
15873 }
15874 } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) {
15875 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});
15876 } else if (ptr_size == .C) {
15877 if (!(try sema.validateExternType(elem_ty, .other))) {
15878 const msg = msg: {
15879 const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
15880 errdefer msg.destroy(sema.gpa);
15881
15882 const src_decl = sema.mod.declPtr(block.src_decl);
15883 try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), elem_ty, .other);
15884
15885 try sema.addDeclaredHereNote(msg, elem_ty);
15886 break :msg msg;
15887 };
15888 return sema.failWithOwnedErrorMsg(block, msg);
15889 }
15890 if (elem_ty.zigTypeTag() == .Opaque) {
15891 return sema.fail(block, src, "C pointers cannot point to opaque types", .{});
15892 }
15893 }
15894
1547215895 const ty = try Type.ptr(sema.arena, mod, .{
1547315896 .size = ptr_size,
1547415897 .mutable = !is_const_val.toBool(),
......@@ -15529,6 +15952,10 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1552915952 const error_set_ty = try error_set_val.toType(&buffer).copy(sema.arena);
1553015953 const payload_ty = try payload_val.toType(&buffer).copy(sema.arena);
1553115954
15955 if (error_set_ty.zigTypeTag() != .ErrorSet) {
15956 return sema.fail(block, src, "Type.ErrorUnion.error_set must be an error set type", .{});
15957 }
15958
1553215959 const ty = try Type.Tag.error_union.create(sema.arena, .{
1553315960 .error_set = error_set_ty,
1553415961 .payload = payload_ty,
......@@ -15542,7 +15969,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1554215969 const decl_index = slice_val.ptr.pointerDecl().?;
1554315970 try sema.ensureDeclAnalyzed(decl_index);
1554415971 const decl = mod.declPtr(decl_index);
15545 const array_val = decl.val.castTag(.aggregate).?.data;
15972 const array_val: []Value = if (decl.val.castTag(.aggregate)) |some| some.data else &.{};
1554615973
1554715974 var names: Module.ErrorSet.NameMap = .{};
1554815975 try names.ensureUnusedCapacity(sema.arena, array_val.len);
......@@ -15554,7 +15981,10 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1555415981 const name_str = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, sema.mod);
1555515982
1555615983 const kv = try mod.getErrorValue(name_str);
15557 names.putAssumeCapacityNoClobber(kv.key, {});
15984 const gop = names.getOrPutAssumeCapacity(kv.key);
15985 if (gop.found_existing) {
15986 return sema.fail(block, src, "duplicate error '{s}'", .{name_str});
15987 }
1555815988 }
1555915989
1556015990 // names must be sorted
......@@ -15636,13 +16066,9 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1563616066 new_decl.owns_tv = true;
1563716067 errdefer mod.abortAnonDecl(new_decl_index);
1563816068
15639 // Enum tag type
15640 var buffer: Value.ToTypeBuffer = undefined;
15641 const int_tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator);
15642
1564316069 enum_obj.* = .{
1564416070 .owner_decl = new_decl_index,
15645 .tag_ty = int_tag_ty,
16071 .tag_ty = Type.@"null",
1564616072 .tag_ty_inferred = false,
1564716073 .fields = .{},
1564816074 .values = .{},
......@@ -15654,6 +16080,15 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1565416080 },
1565516081 };
1565616082
16083 // Enum tag type
16084 var buffer: Value.ToTypeBuffer = undefined;
16085 const int_tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator);
16086
16087 if (int_tag_ty.zigTypeTag() != .Int) {
16088 return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});
16089 }
16090 enum_obj.tag_ty = int_tag_ty;
16091
1565716092 // Fields
1565816093 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));
1565916094 if (fields_len > 0) {
......@@ -15691,6 +16126,8 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1569116126 .mod = mod,
1569216127 });
1569316128 }
16129 } else {
16130 return sema.fail(block, src, "enums must have at least one field", .{});
1569416131 }
1569516132
1569616133 try new_decl.finalizeNewArena(&new_decl_arena);
......@@ -15800,11 +16237,17 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1580016237 };
1580116238
1580216239 // Tag type
16240 var tag_ty_field_names: ?Module.EnumFull.NameMap = null;
1580316241 var enum_field_names: ?*Module.EnumNumbered.NameMap = null;
1580416242 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));
1580516243 if (tag_type_val.optionalValue()) |payload_val| {
1580616244 var buffer: Value.ToTypeBuffer = undefined;
1580716245 union_obj.tag_ty = try payload_val.toType(&buffer).copy(new_decl_arena_allocator);
16246
16247 if (union_obj.tag_ty.zigTypeTag() != .Enum) {
16248 return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{});
16249 }
16250 tag_ty_field_names = try union_obj.tag_ty.enumFields().clone(sema.arena);
1580816251 } else {
1580916252 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(block, fields_len, null);
1581016253 enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields;
......@@ -15836,6 +16279,19 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1583616279 set.putAssumeCapacity(field_name, {});
1583716280 }
1583816281
16282 if (tag_ty_field_names) |*names| {
16283 const enum_has_field = names.orderedRemove(field_name);
16284 if (!enum_has_field) {
16285 const msg = msg: {
16286 const msg = try sema.errMsg(block, src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) });
16287 errdefer msg.destroy(sema.gpa);
16288 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
16289 break :msg msg;
16290 };
16291 return sema.failWithOwnedErrorMsg(block, msg);
16292 }
16293 }
16294
1583916295 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
1584016296 if (gop.found_existing) {
1584116297 // TODO: better source location
......@@ -15848,12 +16304,108 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1584816304 .abi_align = @intCast(u32, alignment_val.toUnsignedInt(target)),
1584916305 };
1585016306 }
16307 } else {
16308 return sema.fail(block, src, "unions must have at least one field", .{});
16309 }
16310
16311 if (tag_ty_field_names) |names| {
16312 if (names.count() > 0) {
16313 const msg = msg: {
16314 const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{});
16315 errdefer msg.destroy(sema.gpa);
16316
16317 const enum_ty = union_obj.tag_ty;
16318 for (names.keys()) |field_name| {
16319 const field_index = enum_ty.enumFieldIndex(field_name).?;
16320 try sema.addFieldErrNote(block, enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name});
16321 }
16322 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
16323 break :msg msg;
16324 };
16325 return sema.failWithOwnedErrorMsg(block, msg);
16326 }
1585116327 }
1585216328
1585316329 try new_decl.finalizeNewArena(&new_decl_arena);
1585416330 return sema.analyzeDeclVal(block, src, new_decl_index);
1585516331 },
15856 .Fn => return sema.fail(block, src, "TODO: Sema.zirReify for Fn", .{}),
16332 .Fn => {
16333 const struct_val = union_val.val.castTag(.aggregate).?.data;
16334 // TODO use reflection instead of magic numbers here
16335 // calling_convention: CallingConvention,
16336 const cc = struct_val[0].toEnum(std.builtin.CallingConvention);
16337 // alignment: comptime_int,
16338 const alignment_val = struct_val[1];
16339 // is_generic: bool,
16340 const is_generic = struct_val[2].toBool();
16341 // is_var_args: bool,
16342 const is_var_args = struct_val[3].toBool();
16343 // return_type: ?type,
16344 const return_type_val = struct_val[4];
16345 // args: []const Param,
16346 const args_val = struct_val[5];
16347
16348 if (is_generic) {
16349 return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{});
16350 }
16351
16352 if (is_var_args and cc != .C) {
16353 return sema.fail(block, src, "varargs functions must have C calling convention", .{});
16354 }
16355
16356 const alignment = @intCast(u29, alignment_val.toUnsignedInt(target)); // TODO: Validate this value.
16357 var buf: Value.ToTypeBuffer = undefined;
16358
16359 const args: []Value = if (args_val.castTag(.aggregate)) |some| some.data else &.{};
16360 var param_types = try sema.arena.alloc(Type, args.len);
16361 var comptime_params = try sema.arena.alloc(bool, args.len);
16362 var noalias_bits: u32 = 0;
16363 for (args) |arg, i| {
16364 const arg_val = arg.castTag(.aggregate).?.data;
16365 // TODO use reflection instead of magic numbers here
16366 // is_generic: bool,
16367 const arg_is_generic = arg_val[0].toBool();
16368 // is_noalias: bool,
16369 const arg_is_noalias = arg_val[1].toBool();
16370 // arg_type: ?type,
16371 const param_type_val = arg_val[2];
16372
16373 if (arg_is_generic) {
16374 return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{});
16375 }
16376
16377 if (arg_is_noalias) {
16378 noalias_bits = @as(u32, 1) << (std.math.cast(u5, i) orelse
16379 return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
16380 }
16381
16382 const param_type = param_type_val.optionalValue() orelse
16383 return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{});
16384
16385 param_types[i] = try param_type.toType(&buf).copy(sema.arena);
16386 }
16387
16388 const return_type = return_type_val.optionalValue() orelse
16389 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
16390
16391 var fn_info = Type.Payload.Function.Data{
16392 .param_types = param_types,
16393 .comptime_params = comptime_params.ptr,
16394 .noalias_bits = noalias_bits,
16395 .return_type = try return_type.toType(&buf).copy(sema.arena),
16396 .alignment = alignment,
16397 .cc = cc,
16398 .is_var_args = is_var_args,
16399 .is_generic = false,
16400 .align_is_generic = false,
16401 .cc_is_generic = false,
16402 .section_is_generic = false,
16403 .addrspace_is_generic = false,
16404 };
16405
16406 const ty = try Type.Tag.function.create(sema.arena, fn_info);
16407 return sema.addType(ty);
16408 },
1585716409 .BoundFn => @panic("TODO delete BoundFn from the language"),
1585816410 .Frame => @panic("TODO implement https://github.com/ziglang/zig/issues/10710"),
1585916411 }
......@@ -15996,6 +16548,11 @@ fn reifyStruct(
1599616548 // alignment: comptime_int,
1599716549 const alignment_val = field_struct_val[4];
1599816550
16551 if (!try sema.intFitsInType(block, src, alignment_val, Type.u32, null)) {
16552 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
16553 }
16554 const abi_align = @intCast(u29, alignment_val.toUnsignedInt(target));
16555
1599916556 const field_name = try name_val.toAllocatedBytes(
1600016557 Type.initTag(.const_slice_u8),
1600116558 new_decl_arena_allocator,
......@@ -16019,7 +16576,7 @@ fn reifyStruct(
1601916576 var buffer: Value.ToTypeBuffer = undefined;
1602016577 gop.value_ptr.* = .{
1602116578 .ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator),
16022 .abi_align = @intCast(u32, alignment_val.toUnsignedInt(target)),
16579 .abi_align = abi_align,
1602316580 .default_val = default_val,
1602416581 .is_comptime = is_comptime_val.toBool(),
1602516582 .offset = undefined,
......@@ -16710,6 +17267,46 @@ fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileEr
1671017267 }
1671117268}
1671217269
17270fn checkInvalidPtrArithmetic(
17271 sema: *Sema,
17272 block: *Block,
17273 src: LazySrcLoc,
17274 ty: Type,
17275 zir_tag: Zir.Inst.Tag,
17276) CompileError!void {
17277 switch (try ty.zigTypeTagOrPoison()) {
17278 .Pointer => switch (ty.ptrSize()) {
17279 .One, .Slice => return,
17280 .Many, .C => return sema.fail(
17281 block,
17282 src,
17283 "invalid pointer arithmetic operand: '{s}''",
17284 .{@tagName(zir_tag)},
17285 ),
17286 },
17287 else => return,
17288 }
17289}
17290
17291fn checkArithmeticOp(
17292 sema: *Sema,
17293 block: *Block,
17294 src: LazySrcLoc,
17295 scalar_tag: std.builtin.TypeId,
17296 lhs_zig_ty_tag: std.builtin.TypeId,
17297 rhs_zig_ty_tag: std.builtin.TypeId,
17298 zir_tag: Zir.Inst.Tag,
17299) CompileError!void {
17300 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
17301 const is_float = scalar_tag == .Float or scalar_tag == .ComptimeFloat;
17302
17303 if (!is_int and !(is_float and floatOpAllowed(zir_tag))) {
17304 return sema.fail(block, src, "invalid operands to binary expression: '{s}' and '{s}'", .{
17305 @tagName(lhs_zig_ty_tag), @tagName(rhs_zig_ty_tag),
17306 });
17307 }
17308}
17309
1671317310fn checkPtrOperand(
1671417311 sema: *Sema,
1671517312 block: *Block,
......@@ -20241,7 +20838,7 @@ fn tupleFieldVal(
2024120838 return tupleFieldValByIndex(sema, block, src, tuple_byval, field_index, tuple_ty);
2024220839}
2024320840
20244/// Don't forget to check for "len" before calling this.
20841/// Asserts that `field_name` is not "len".
2024520842fn tupleFieldIndex(
2024620843 sema: *Sema,
2024720844 block: *Block,
......@@ -20249,8 +20846,12 @@ fn tupleFieldIndex(
2024920846 field_name: []const u8,
2025020847 field_name_src: LazySrcLoc,
2025120848) CompileError!u32 {
20849 assert(!std.mem.eql(u8, field_name, "len"));
2025220850 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {
2025320851 if (field_index < tuple_ty.structFieldCount()) return field_index;
20852 return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{
20853 field_name, tuple_ty.fmt(sema.mod),
20854 });
2025420855 } else |_| {}
2025520856
2025620857 return sema.fail(block, field_name_src, "no field named '{s}' in tuple '{}'", .{
......@@ -23927,8 +24528,7 @@ fn coerceTupleToStruct(
2392724528 const struct_ty = try sema.resolveTypeFields(block, dest_ty_src, dest_ty);
2392824529
2392924530 if (struct_ty.isTupleOrAnonStruct()) {
23930 // NOTE remember to handle comptime fields
23931 return sema.fail(block, dest_ty_src, "TODO: implement coercion from tuples to tuples", .{});
24531 return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);
2393224532 }
2393324533
2393424534 const fields = struct_ty.structFields();
......@@ -24011,6 +24611,110 @@ fn coerceTupleToStruct(
2401124611 );
2401224612}
2401324613
24614fn coerceTupleToTuple(
24615 sema: *Sema,
24616 block: *Block,
24617 tuple_ty: Type,
24618 inst: Air.Inst.Ref,
24619 inst_src: LazySrcLoc,
24620) !Air.Inst.Ref {
24621 const field_count = tuple_ty.structFieldCount();
24622 const field_vals = try sema.arena.alloc(Value, field_count);
24623 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
24624 mem.set(Air.Inst.Ref, field_refs, .none);
24625
24626 const inst_ty = sema.typeOf(inst);
24627 const tuple = inst_ty.tupleFields();
24628 var runtime_src: ?LazySrcLoc = null;
24629 for (tuple.types) |_, i_usize| {
24630 const i = @intCast(u32, i_usize);
24631 const field_src = inst_src; // TODO better source location
24632 const field_name = if (inst_ty.castTag(.anon_struct)) |payload|
24633 payload.data.names[i]
24634 else
24635 try std.fmt.allocPrint(sema.arena, "{d}", .{i});
24636
24637 if (mem.eql(u8, field_name, "len")) {
24638 return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{});
24639 }
24640
24641 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);
24642
24643 const field_ty = tuple_ty.structFieldType(i);
24644 const default_val = tuple_ty.structFieldDefaultValue(i);
24645 const elem_ref = try tupleField(sema, block, inst_src, inst, field_src, i);
24646 const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);
24647 field_refs[field_index] = coerced;
24648 if (default_val.tag() != .unreachable_value) {
24649 const init_val = (try sema.resolveMaybeUndefVal(block, field_src, coerced)) orelse {
24650 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime known");
24651 };
24652
24653 if (!init_val.eql(default_val, field_ty, sema.mod)) {
24654 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, i);
24655 }
24656 }
24657 if (runtime_src == null) {
24658 if (try sema.resolveMaybeUndefVal(block, field_src, coerced)) |field_val| {
24659 field_vals[field_index] = field_val;
24660 } else {
24661 runtime_src = field_src;
24662 }
24663 }
24664 }
24665
24666 // Populate default field values and report errors for missing fields.
24667 var root_msg: ?*Module.ErrorMsg = null;
24668
24669 for (field_refs) |*field_ref, i| {
24670 if (field_ref.* != .none) continue;
24671
24672 const default_val = tuple_ty.structFieldDefaultValue(i);
24673 const field_ty = tuple_ty.structFieldType(i);
24674
24675 const field_src = inst_src; // TODO better source location
24676 if (default_val.tag() == .unreachable_value) {
24677 if (tuple_ty.isTuple()) {
24678 const template = "missing tuple field: {d}";
24679 if (root_msg) |msg| {
24680 try sema.errNote(block, field_src, msg, template, .{i});
24681 } else {
24682 root_msg = try sema.errMsg(block, field_src, template, .{i});
24683 }
24684 continue;
24685 }
24686 const template = "missing struct field: {s}";
24687 const args = .{tuple_ty.structFieldName(i)};
24688 if (root_msg) |msg| {
24689 try sema.errNote(block, field_src, msg, template, args);
24690 } else {
24691 root_msg = try sema.errMsg(block, field_src, template, args);
24692 }
24693 continue;
24694 }
24695 if (runtime_src == null) {
24696 field_vals[i] = default_val;
24697 } else {
24698 field_ref.* = try sema.addConstant(field_ty, default_val);
24699 }
24700 }
24701
24702 if (root_msg) |msg| {
24703 try sema.addDeclaredHereNote(msg, tuple_ty);
24704 return sema.failWithOwnedErrorMsg(block, msg);
24705 }
24706
24707 if (runtime_src) |rs| {
24708 try sema.requireRuntimeBlock(block, inst_src, rs);
24709 return block.addAggregateInit(tuple_ty, field_refs);
24710 }
24711
24712 return sema.addConstant(
24713 tuple_ty,
24714 try Value.Tag.aggregate.create(sema.arena, field_vals),
24715 );
24716}
24717
2401424718fn analyzeDeclVal(
2401524719 sema: *Sema,
2401624720 block: *Block,
......@@ -24446,7 +25150,10 @@ fn analyzeSlice(
2444625150 if (!end_is_len) {
2444725151 const end = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
2444825152 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {
24449 if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| {
25153 if (try sema.resolveMaybeUndefVal(block, src, ptr_or_slice)) |slice_val| {
25154 if (slice_val.isUndef()) {
25155 return sema.fail(block, src, "slice of undefined", .{});
25156 }
2445025157 const has_sentinel = slice_ty.sentinel() != null;
2445125158 var int_payload: Value.Payload.U64 = .{
2445225159 .base = .{ .tag = .int_u64 },
......@@ -24509,8 +25216,8 @@ fn analyzeSlice(
2450925216 };
2451025217
2451125218 // requirement: start <= end
24512 if (try sema.resolveDefinedValue(block, src, end)) |end_val| {
24513 if (try sema.resolveDefinedValue(block, src, start)) |start_val| {
25219 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {
25220 if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| {
2451425221 if (try sema.compare(block, src, start_val, .gt, end_val, Type.usize)) {
2451525222 return sema.fail(
2451625223 block,
......@@ -24522,6 +25229,45 @@ fn analyzeSlice(
2452225229 },
2452325230 );
2452425231 }
25232 if (try sema.resolveMaybeUndefVal(block, ptr_src, new_ptr)) |ptr_val| sentinel_check: {
25233 const expected_sentinel = sentinel orelse break :sentinel_check;
25234 const start_int = start_val.getUnsignedInt(sema.mod.getTarget()).?;
25235 const end_int = end_val.getUnsignedInt(sema.mod.getTarget()).?;
25236 const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int);
25237
25238 const elem_ptr = try ptr_val.elemPtr(sema.typeOf(new_ptr), sema.arena, sentinel_index, sema.mod);
25239 const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty, false);
25240 const actual_sentinel = switch (res) {
25241 .runtime_load => break :sentinel_check,
25242 .val => |v| v,
25243 .needed_well_defined => |ty| return sema.fail(
25244 block,
25245 src,
25246 "comptime dereference requires '{}' to have a well-defined layout, but it does not.",
25247 .{ty.fmt(sema.mod)},
25248 ),
25249 .out_of_bounds => |ty| return sema.fail(
25250 block,
25251 end_src,
25252 "slice end index {d} exceeds bounds of containing decl of type '{}'",
25253 .{ end_int, ty.fmt(sema.mod) },
25254 ),
25255 };
25256
25257 if (!actual_sentinel.eql(expected_sentinel, elem_ty, sema.mod)) {
25258 const msg = msg: {
25259 const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{});
25260 errdefer msg.destroy(sema.gpa);
25261 try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{
25262 expected_sentinel.fmtValue(elem_ty, sema.mod),
25263 actual_sentinel.fmtValue(elem_ty, sema.mod),
25264 });
25265
25266 break :msg msg;
25267 };
25268 return sema.failWithOwnedErrorMsg(block, msg);
25269 }
25270 }
2452525271 }
2452625272 }
2452725273
......@@ -26884,7 +27630,8 @@ fn enumFieldSrcLoc(
2688427630 .container_decl_arg_trailing,
2688527631 => tree.containerDeclArg(enum_node),
2688627632
26887 else => unreachable,
27633 // Container was constructed with `@Type`.
27634 else => return LazySrcLoc.nodeOffset(node_offset),
2688827635 };
2688927636 var it_index: usize = 0;
2689027637 for (container_decl.ast.members) |member_node| {
......@@ -27161,9 +27908,36 @@ pub fn analyzeAddrspace(
2716127908/// Returns `null` if the pointer contents cannot be loaded at comptime.
2716227909fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr_ty: Type) CompileError!?Value {
2716327910 const load_ty = ptr_ty.childType();
27911 const res = try sema.pointerDerefExtra(block, src, ptr_val, load_ty, true);
27912 switch (res) {
27913 .runtime_load => return null,
27914 .val => |v| return v,
27915 .needed_well_defined => |ty| return sema.fail(
27916 block,
27917 src,
27918 "comptime dereference requires '{}' to have a well-defined layout, but it does not.",
27919 .{ty.fmt(sema.mod)},
27920 ),
27921 .out_of_bounds => |ty| return sema.fail(
27922 block,
27923 src,
27924 "dereference of '{}' exceeds bounds of containing decl of type '{}'",
27925 .{ ptr_ty.fmt(sema.mod), ty.fmt(sema.mod) },
27926 ),
27927 }
27928}
27929
27930const DerefResult = union(enum) {
27931 runtime_load,
27932 val: Value,
27933 needed_well_defined: Type,
27934 out_of_bounds: Type,
27935};
27936
27937fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, load_ty: Type, want_mutable: bool) CompileError!DerefResult {
2716427938 const target = sema.mod.getTarget();
2716527939 const deref = sema.beginComptimePtrLoad(block, src, ptr_val, load_ty) catch |err| switch (err) {
27166 error.RuntimeLoad => return null,
27940 error.RuntimeLoad => return DerefResult{ .runtime_load = {} },
2716727941 else => |e| return e,
2716827942 };
2716927943
......@@ -27174,39 +27948,40 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr
2717427948 if (coerce_in_mem_ok) {
2717527949 // We have a Value that lines up in virtual memory exactly with what we want to load,
2717627950 // and it is in-memory coercible to load_ty. It may be returned without modifications.
27177 if (deref.is_mutable) {
27951 if (deref.is_mutable and want_mutable) {
2717827952 // The decl whose value we are obtaining here may be overwritten with
2717927953 // a different value upon further semantic analysis, which would
2718027954 // invalidate this memory. So we must copy here.
27181 return try tv.val.copy(sema.arena);
27955 return DerefResult{ .val = try tv.val.copy(sema.arena) };
2718227956 }
27183 return tv.val;
27957 return DerefResult{ .val = tv.val };
2718427958 }
2718527959 }
2718627960
2718727961 // The type is not in-memory coercible or the direct dereference failed, so it must
2718827962 // be bitcast according to the pointer type we are performing the load through.
27189 if (!load_ty.hasWellDefinedLayout())
27190 return sema.fail(block, src, "comptime dereference requires '{}' to have a well-defined layout, but it does not.", .{load_ty.fmt(sema.mod)});
27963 if (!load_ty.hasWellDefinedLayout()) {
27964 return DerefResult{ .needed_well_defined = load_ty };
27965 }
2719127966
2719227967 const load_sz = try sema.typeAbiSize(block, src, load_ty);
2719327968
2719427969 // Try the smaller bit-cast first, since that's more efficient than using the larger `parent`
2719527970 if (deref.pointee) |tv| if (load_sz <= try sema.typeAbiSize(block, src, tv.ty))
27196 return try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0);
27971 return DerefResult{ .val = try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0) };
2719727972
2719827973 // If that fails, try to bit-cast from the largest parent value with a well-defined layout
2719927974 if (deref.parent) |parent| if (load_sz + parent.byte_offset <= try sema.typeAbiSize(block, src, parent.tv.ty))
27200 return try sema.bitCastVal(block, src, parent.tv.val, parent.tv.ty, load_ty, parent.byte_offset);
27975 return DerefResult{ .val = try sema.bitCastVal(block, src, parent.tv.val, parent.tv.ty, load_ty, parent.byte_offset) };
2720127976
2720227977 if (deref.ty_without_well_defined_layout) |bad_ty| {
2720327978 // We got no parent for bit-casting, or the parent we got was too small. Either way, the problem
2720427979 // is that some type we encountered when de-referencing does not have a well-defined layout.
27205 return sema.fail(block, src, "comptime dereference requires '{}' to have a well-defined layout, but it does not.", .{bad_ty.fmt(sema.mod)});
27980 return DerefResult{ .needed_well_defined = bad_ty };
2720627981 } else {
2720727982 // If all encountered types had well-defined layouts, the parent is the root decl and it just
2720827983 // wasn't big enough for the load.
27209 return sema.fail(block, src, "dereference of '{}' exceeds bounds of containing decl of type '{}'", .{ ptr_ty.fmt(sema.mod), deref.parent.?.tv.ty.fmt(sema.mod) });
27984 return DerefResult{ .out_of_bounds = deref.parent.?.tv.ty };
2721027985 }
2721127986}
2721227987
src/TypedValue.zig+10-4
......@@ -73,6 +73,9 @@ pub fn print(
7373 const target = mod.getTarget();
7474 var val = tv.val;
7575 var ty = tv.ty;
76 if (val.isVariable(mod))
77 return writer.writeAll("(variable)");
78
7679 while (true) switch (val.tag()) {
7780 .u1_type => return writer.writeAll("u1"),
7881 .u8_type => return writer.writeAll("u8"),
......@@ -155,9 +158,12 @@ pub fn print(
155158 }
156159 try print(.{
157160 .ty = ty.structFieldType(i),
158 .val = ty.structFieldValueComptime(i) orelse b: {
159 const vals = val.castTag(.aggregate).?.data;
160 break :b vals[i];
161 .val = switch (ty.containerLayout()) {
162 .Packed => val.castTag(.aggregate).?.data[i],
163 else => ty.structFieldValueComptime(i) orelse b: {
164 const vals = val.castTag(.aggregate).?.data;
165 break :b vals[i];
166 },
161167 },
162168 }, writer, level - 1, mod);
163169 }
......@@ -241,7 +247,7 @@ pub fn print(
241247 mod.declPtr(val.castTag(.function).?.data.owner_decl).name,
242248 }),
243249 .extern_fn => return writer.writeAll("(extern function)"),
244 .variable => return writer.writeAll("(variable)"),
250 .variable => unreachable,
245251 .decl_ref_mut => {
246252 const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;
247253 const decl = mod.declPtr(decl_index);
src/Zir.zig+12-1
......@@ -280,6 +280,9 @@ pub const Inst = struct {
280280 /// break instruction in a block, and the target block is the parent.
281281 /// Uses the `break` union field.
282282 break_inline,
283 /// Checks that comptime control flow does not happen inside a runtime block.
284 /// Uses the `node` union field.
285 check_comptime_control_flow,
283286 /// Function call.
284287 /// Uses the `pl_node` union field with payload `Call`.
285288 /// AST node is the function call.
......@@ -1266,6 +1269,7 @@ pub const Inst = struct {
12661269 .repeat_inline,
12671270 .panic,
12681271 .panic_comptime,
1272 .check_comptime_control_flow,
12691273 => true,
12701274 };
12711275 }
......@@ -1315,6 +1319,7 @@ pub const Inst = struct {
13151319 .set_runtime_safety,
13161320 .memcpy,
13171321 .memset,
1322 .check_comptime_control_flow,
13181323 => true,
13191324
13201325 .param,
......@@ -1595,6 +1600,7 @@ pub const Inst = struct {
15951600 .bool_br_or = .bool_br,
15961601 .@"break" = .@"break",
15971602 .break_inline = .@"break",
1603 .check_comptime_control_flow = .node,
15981604 .call = .pl_node,
15991605 .cmp_lt = .pl_node,
16001606 .cmp_lte = .pl_node,
......@@ -1703,7 +1709,7 @@ pub const Inst = struct {
17031709 .switch_capture_multi_ref = .switch_capture,
17041710 .array_base_ptr = .un_node,
17051711 .field_base_ptr = .un_node,
1706 .validate_array_init_ty = .un_node,
1712 .validate_array_init_ty = .pl_node,
17071713 .validate_struct_init_ty = .un_node,
17081714 .validate_struct_init = .pl_node,
17091715 .validate_struct_init_comptime = .pl_node,
......@@ -3537,6 +3543,11 @@ pub const Inst = struct {
35373543 line: u32,
35383544 column: u32,
35393545 };
3546
3547 pub const ArrayInit = struct {
3548 ty: Ref,
3549 init_count: u32,
3550 };
35403551};
35413552
35423553pub const SpecialProng = enum { none, @"else", under };
src/arch/arm/CodeGen.zig+34-27
......@@ -4300,17 +4300,6 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
43004300 );
43014301 defer self.gpa.free(liveness.deaths);
43024302
4303 // If the condition dies here in this switch instruction, process
4304 // that death now instead of later as this has an effect on
4305 // whether it needs to be spilled in the branches
4306 if (self.liveness.operandDies(inst, 0)) {
4307 const op_int = @enumToInt(pl_op.operand);
4308 if (op_int >= Air.Inst.Ref.typed_value_map.len) {
4309 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
4310 self.processDeath(op_index);
4311 }
4312 }
4313
43144303 var extra_index: usize = switch_br.end;
43154304 var case_i: u32 = 0;
43164305 while (case_i < switch_br.data.cases_len) : (case_i += 1) {
......@@ -4320,21 +4309,43 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
43204309 const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len];
43214310 extra_index = case.end + items.len + case_body.len;
43224311
4323 var relocs = try self.gpa.alloc(u32, items.len);
4324 defer self.gpa.free(relocs);
4325
4326 if (items.len == 1) {
4312 // For every item, we compare it to condition and branch into
4313 // the prong if they are equal. After we compared to all
4314 // items, we branch into the next prong (or if no other prongs
4315 // exist out of the switch statement).
4316 //
4317 // cmp condition, item1
4318 // beq prong
4319 // cmp condition, item2
4320 // beq prong
4321 // cmp condition, item3
4322 // beq prong
4323 // b out
4324 // prong: ...
4325 // ...
4326 // out: ...
4327 const branch_into_prong_relocs = try self.gpa.alloc(u32, items.len);
4328 defer self.gpa.free(branch_into_prong_relocs);
4329
4330 for (items) |item, idx| {
43274331 const condition = try self.resolveInst(pl_op.operand);
4328 const item = try self.resolveInst(items[0]);
4332 const item_mcv = try self.resolveInst(item);
43294333
43304334 const operands: BinOpOperands = .{ .mcv = .{
43314335 .lhs = condition,
4332 .rhs = item,
4336 .rhs = item_mcv,
43334337 } };
4334 const cmp_result = try self.cmp(operands, condition_ty, .eq);
4335 relocs[0] = try self.condBr(cmp_result);
4336 } else {
4337 return self.fail("TODO switch with multiple items", .{});
4338 const cmp_result = try self.cmp(operands, condition_ty, .neq);
4339 branch_into_prong_relocs[idx] = try self.condBr(cmp_result);
4340 }
4341
4342 const branch_away_from_prong_reloc = try self.addInst(.{
4343 .tag = .b,
4344 .data = .{ .inst = undefined }, // populated later through performReloc
4345 });
4346
4347 for (branch_into_prong_relocs) |reloc| {
4348 try self.performReloc(reloc);
43384349 }
43394350
43404351 // Capture the state of register and stack allocation state so that we can revert to it.
......@@ -4369,9 +4380,7 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
43694380 self.next_stack_offset = parent_next_stack_offset;
43704381 self.register_manager.free_registers = parent_free_registers;
43714382
4372 for (relocs) |reloc| {
4373 try self.performReloc(reloc);
4374 }
4383 try self.performReloc(branch_away_from_prong_reloc);
43754384 }
43764385
43774386 if (switch_br.data.else_body_len > 0) {
......@@ -4414,9 +4423,7 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
44144423 // in airCondBr.
44154424 }
44164425
4417 // We already took care of pl_op.operand earlier, so we're going
4418 // to pass .none here
4419 return self.finishAir(inst, .unreach, .{ .none, .none, .none });
4426 return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });
44204427}
44214428
44224429fn performReloc(self: *Self, inst: Mir.Inst.Index) !void {
src/arch/wasm/CodeGen.zig+2-2
......@@ -603,7 +603,7 @@ stack_alignment: u32 = 16,
603603
604604const InnerError = error{
605605 OutOfMemory,
606 /// An error occured when trying to lower AIR to MIR.
606 /// An error occurred when trying to lower AIR to MIR.
607607 CodegenFail,
608608 /// Can occur when dereferencing a pointer that points to a `Decl` of which the analysis has failed
609609 AnalysisFail,
......@@ -4410,7 +4410,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
44104410 }
44114411
44124412 // We store the bit if it's overflowed or not in this. As it's zero-initialized
4413 // we only need to update it if an overflow (or underflow) occured.
4413 // we only need to update it if an overflow (or underflow) occurred.
44144414 const overflow_bit = try self.allocLocal(Type.initTag(.u1));
44154415 const int_info = lhs_ty.intInfo(self.target);
44164416 const wasm_bits = toWasmBits(int_info.bits) orelse {
src/clang.zig+3
......@@ -1913,3 +1913,6 @@ extern fn ZigClangLoadFromCommandLine(
19131913 errors_len: *usize,
19141914 resources_path: [*:0]const u8,
19151915) ?*ASTUnit;
1916
1917pub const isLLVMUsingSeparateLibcxx = ZigClangIsLLVMUsingSeparateLibcxx;
1918extern fn ZigClangIsLLVMUsingSeparateLibcxx() bool;
src/codegen/llvm.zig+109-32
......@@ -5491,22 +5491,26 @@ pub const FuncGen = struct {
54915491 defer arena_allocator.deinit();
54925492 const arena = arena_allocator.allocator();
54935493
5494 const return_count: u8 = for (outputs) |output| {
5495 if (output == .none) break 1;
5496 } else 0;
5497 const llvm_params_len = inputs.len + outputs.len - return_count;
5498 const llvm_param_types = try arena.alloc(*const llvm.Type, llvm_params_len);
5499 const llvm_param_values = try arena.alloc(*const llvm.Value, llvm_params_len);
5500 const llvm_param_attrs = try arena.alloc(bool, llvm_params_len);
5494 // The exact number of return / parameter values depends on which output values
5495 // are passed by reference as indirect outputs (determined below).
5496 const max_return_count = outputs.len;
5497 const llvm_ret_types = try arena.alloc(*const llvm.Type, max_return_count);
5498 const llvm_ret_indirect = try arena.alloc(bool, max_return_count);
5499
5500 const max_param_count = inputs.len + outputs.len;
5501 const llvm_param_types = try arena.alloc(*const llvm.Type, max_param_count);
5502 const llvm_param_values = try arena.alloc(*const llvm.Value, max_param_count);
5503 const llvm_param_attrs = try arena.alloc(bool, max_param_count);
55015504 const target = self.dg.module.getTarget();
55025505
5506 var llvm_ret_i: usize = 0;
55035507 var llvm_param_i: usize = 0;
5504 var total_i: usize = 0;
5508 var total_i: u16 = 0;
55055509
5506 var name_map: std.StringArrayHashMapUnmanaged(void) = .{};
5507 try name_map.ensureUnusedCapacity(arena, outputs.len + inputs.len);
5510 var name_map: std.StringArrayHashMapUnmanaged(u16) = .{};
5511 try name_map.ensureUnusedCapacity(arena, max_param_count);
55085512
5509 for (outputs) |output| {
5513 for (outputs) |output, i| {
55105514 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
55115515 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
55125516 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
......@@ -5519,15 +5523,30 @@ pub const FuncGen = struct {
55195523 llvm_constraints.appendAssumeCapacity(',');
55205524 }
55215525 llvm_constraints.appendAssumeCapacity('=');
5526
5527 // Pass any non-return outputs indirectly, if the constraint accepts a memory location
5528 llvm_ret_indirect[i] = (output != .none) and constraintAllowsMemory(constraint);
55225529 if (output != .none) {
55235530 try llvm_constraints.ensureUnusedCapacity(self.gpa, llvm_constraints.capacity + 1);
5524 llvm_constraints.appendAssumeCapacity('*');
5525
55265531 const output_inst = try self.resolveInst(output);
5527 llvm_param_values[llvm_param_i] = output_inst;
5528 llvm_param_types[llvm_param_i] = output_inst.typeOf();
5529 llvm_param_attrs[llvm_param_i] = true;
5530 llvm_param_i += 1;
5532
5533 if (llvm_ret_indirect[i]) {
5534 // Pass the result by reference as an indirect output (e.g. "=*m")
5535 llvm_constraints.appendAssumeCapacity('*');
5536
5537 llvm_param_values[llvm_param_i] = output_inst;
5538 llvm_param_types[llvm_param_i] = output_inst.typeOf();
5539 llvm_param_attrs[llvm_param_i] = true;
5540 llvm_param_i += 1;
5541 } else {
5542 // Pass the result directly (e.g. "=r")
5543 llvm_ret_types[llvm_ret_i] = output_inst.typeOf().getElementType();
5544 llvm_ret_i += 1;
5545 }
5546 } else {
5547 const ret_ty = self.air.typeOfIndex(inst);
5548 llvm_ret_types[llvm_ret_i] = try self.dg.lowerType(ret_ty);
5549 llvm_ret_i += 1;
55315550 }
55325551
55335552 // LLVM uses commas internally to separate different constraints,
......@@ -5536,13 +5555,16 @@ pub const FuncGen = struct {
55365555 // to GCC's inline assembly.
55375556 // http://llvm.org/docs/LangRef.html#constraint-codes
55385557 for (constraint[1..]) |byte| {
5539 llvm_constraints.appendAssumeCapacity(switch (byte) {
5540 ',' => '|',
5541 else => byte,
5542 });
5558 switch (byte) {
5559 ',' => llvm_constraints.appendAssumeCapacity('|'),
5560 '*' => {}, // Indirect outputs are handled above
5561 else => llvm_constraints.appendAssumeCapacity(byte),
5562 }
55435563 }
55445564
5545 name_map.putAssumeCapacityNoClobber(name, {});
5565 if (!std.mem.eql(u8, name, "_")) {
5566 name_map.putAssumeCapacityNoClobber(name, total_i);
5567 }
55465568 total_i += 1;
55475569 }
55485570
......@@ -5594,7 +5616,7 @@ pub const FuncGen = struct {
55945616 }
55955617
55965618 if (!std.mem.eql(u8, name, "_")) {
5597 name_map.putAssumeCapacityNoClobber(name, {});
5619 name_map.putAssumeCapacityNoClobber(name, total_i);
55985620 }
55995621
56005622 // In the case of indirect inputs, LLVM requires the callsite to have
......@@ -5625,6 +5647,11 @@ pub const FuncGen = struct {
56255647 }
56265648 }
56275649
5650 // We have finished scanning through all inputs/outputs, so the number of
5651 // parameters and return values is known.
5652 const param_count = llvm_param_i;
5653 const return_count = llvm_ret_i;
5654
56285655 // For some targets, Clang unconditionally adds some clobbers to all inline assembly.
56295656 // While this is probably not strictly necessary, if we don't follow Clang's lead
56305657 // here then we may risk tripping LLVM bugs since anything not used by Clang tends
......@@ -5682,7 +5709,7 @@ pub const FuncGen = struct {
56825709 const name = asm_source[name_start..i];
56835710 state = .start;
56845711
5685 const index = name_map.getIndex(name) orelse {
5712 const index = name_map.get(name) orelse {
56865713 // we should validate the assembly in Sema; by now it is too late
56875714 return self.todo("unknown input or output name: '{s}'", .{name});
56885715 };
......@@ -5693,12 +5720,20 @@ pub const FuncGen = struct {
56935720 }
56945721 }
56955722
5696 const ret_ty = self.air.typeOfIndex(inst);
5697 const ret_llvm_ty = try self.dg.lowerType(ret_ty);
5723 const ret_llvm_ty = switch (return_count) {
5724 0 => self.context.voidType(),
5725 1 => llvm_ret_types[0],
5726 else => self.context.structType(
5727 llvm_ret_types.ptr,
5728 @intCast(c_uint, return_count),
5729 .False,
5730 ),
5731 };
5732
56985733 const llvm_fn_ty = llvm.functionType(
56995734 ret_llvm_ty,
57005735 llvm_param_types.ptr,
5701 @intCast(c_uint, llvm_param_types.len),
5736 @intCast(c_uint, param_count),
57025737 .False,
57035738 );
57045739 const asm_fn = llvm.getInlineAsm(
......@@ -5715,18 +5750,40 @@ pub const FuncGen = struct {
57155750 const call = self.builder.buildCall(
57165751 asm_fn,
57175752 llvm_param_values.ptr,
5718 @intCast(c_uint, llvm_param_values.len),
5753 @intCast(c_uint, param_count),
57195754 .C,
57205755 .Auto,
57215756 "",
57225757 );
5723 for (llvm_param_attrs) |need_elem_ty, i| {
5758 for (llvm_param_attrs[0..param_count]) |need_elem_ty, i| {
57245759 if (need_elem_ty) {
57255760 const elem_ty = llvm_param_types[i].getElementType();
57265761 llvm.setCallElemTypeAttr(call, i, elem_ty);
57275762 }
57285763 }
5729 return call;
5764
5765 var ret_val = call;
5766 llvm_ret_i = 0;
5767 for (outputs) |output, i| {
5768 if (llvm_ret_indirect[i]) continue;
5769
5770 const output_value = if (return_count > 1) b: {
5771 break :b self.builder.buildExtractValue(call, @intCast(c_uint, llvm_ret_i), "");
5772 } else call;
5773
5774 if (output != .none) {
5775 const output_ptr = try self.resolveInst(output);
5776 const output_ptr_ty = self.air.typeOf(output);
5777
5778 const store_inst = self.builder.buildStore(output_value, output_ptr);
5779 store_inst.setAlignment(output_ptr_ty.ptrAlignment(target));
5780 } else {
5781 ret_val = output_value;
5782 }
5783 llvm_ret_i += 1;
5784 }
5785
5786 return ret_val;
57305787 }
57315788
57325789 fn airIsNonNull(
......@@ -9709,10 +9766,30 @@ fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u1 {
97099766 return @boolToInt(Type.anyerror.abiAlignment(target) <= payload_ty.abiAlignment(target));
97109767}
97119768
9769/// Returns true for asm constraint (e.g. "=*m", "=r") if it accepts a memory location
9770///
9771/// See also TargetInfo::validateOutputConstraint, AArch64TargetInfo::validateAsmConstraint, etc. in Clang
97129772fn constraintAllowsMemory(constraint: []const u8) bool {
9713 return constraint[0] == 'm';
9773 // TODO: This implementation is woefully incomplete.
9774 for (constraint) |byte| {
9775 switch (byte) {
9776 '=', '*', ',', '&' => {},
9777 'm', 'o', 'X', 'g' => return true,
9778 else => {},
9779 }
9780 } else return false;
97149781}
97159782
9783/// Returns true for asm constraint (e.g. "=*m", "=r") if it accepts a register
9784///
9785/// See also TargetInfo::validateOutputConstraint, AArch64TargetInfo::validateAsmConstraint, etc. in Clang
97169786fn constraintAllowsRegister(constraint: []const u8) bool {
9717 return constraint[0] != 'm';
9787 // TODO: This implementation is woefully incomplete.
9788 for (constraint) |byte| {
9789 switch (byte) {
9790 '=', '*', ',', '&' => {},
9791 'm', 'o' => {},
9792 else => return true,
9793 }
9794 } else return false;
97189795}
src/link/Elf.zig+9
......@@ -1592,6 +1592,15 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
15921592 }
15931593 }
15941594 }
1595 for (self.base.options.objects) |obj| {
1596 if (Compilation.classifyFileExt(obj.path) == .shared_library) {
1597 const lib_dir_path = std.fs.path.dirname(obj.path).?;
1598 if ((try rpath_table.fetchPut(lib_dir_path, {})) == null) {
1599 try argv.append("-rpath");
1600 try argv.append(lib_dir_path);
1601 }
1602 }
1603 }
15951604 }
15961605
15971606 for (self.base.options.lib_dirs) |lib_dir| {
src/main.zig+24-1
......@@ -174,6 +174,17 @@ pub fn main() anyerror!void {
174174 return mainArgs(gpa, arena, args);
175175}
176176
177/// Check that LLVM and Clang have been linked properly so that they are using the same
178/// libc++ and can safely share objects with pointers to static variables in libc++
179fn verifyLibcxxCorrectlyLinked() void {
180 if (build_options.have_llvm and ZigClangIsLLVMUsingSeparateLibcxx()) {
181 fatal(
182 \\Zig was built/linked incorrectly: LLVM and Clang have separate copies of libc++
183 \\ If you are dynamically linking LLVM, make sure you dynamically link libc++ too
184 , .{});
185 }
186}
187
177188pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
178189 if (args.len <= 1) {
179190 std.log.info("{s}", .{usage});
......@@ -261,8 +272,12 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
261272 const stdout = io.getStdOut().writer();
262273 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, info.target);
263274 } else if (mem.eql(u8, cmd, "version")) {
264 return std.io.getStdOut().writeAll(build_options.version ++ "\n");
275 try std.io.getStdOut().writeAll(build_options.version ++ "\n");
276 // Check libc++ linkage to make sure Zig was built correctly, but only for "env" and "version"
277 // to avoid affecting the startup time for build-critical commands (check takes about ~10 μs)
278 return verifyLibcxxCorrectlyLinked();
265279 } else if (mem.eql(u8, cmd, "env")) {
280 verifyLibcxxCorrectlyLinked();
266281 return @import("print_env.zig").cmdEnv(arena, cmd_args, io.getStdOut().writer());
267282 } else if (mem.eql(u8, cmd, "zen")) {
268283 return io.getStdOut().writeAll(info_zen);
......@@ -858,6 +873,12 @@ fn buildOutputType(
858873 ) catch |err| {
859874 fatal("Failed to add package at path {s}: {s}", .{ pkg_path.?, @errorName(err) });
860875 };
876
877 if (mem.eql(u8, pkg_name.?, "std") or mem.eql(u8, pkg_name.?, "root") or mem.eql(u8, pkg_name.?, "builtin")) {
878 fatal("unable to add package '{s}' -> '{s}': conflicts with builtin package", .{ pkg_name.?, pkg_path.? });
879 } else if (cur_pkg.table.get(pkg_name.?)) |prev| {
880 fatal("unable to add package '{s}' -> '{s}': already exists as '{s}", .{ pkg_name.?, pkg_path.?, prev.root_src_path });
881 }
861882 try cur_pkg.addAndAdopt(gpa, pkg_name.?, new_cur_pkg);
862883 cur_pkg = new_cur_pkg;
863884 } else if (mem.eql(u8, arg, "--pkg-end")) {
......@@ -4481,6 +4502,8 @@ pub const info_zen =
44814502 \\
44824503;
44834504
4505extern fn ZigClangIsLLVMUsingSeparateLibcxx() bool;
4506
44844507extern "c" fn ZigClang_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
44854508extern "c" fn ZigLlvmAr_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
44864509
src/print_zir.zig+14-1
......@@ -229,7 +229,6 @@ const Writer = struct {
229229 .switch_cond_ref,
230230 .array_base_ptr,
231231 .field_base_ptr,
232 .validate_array_init_ty,
233232 .validate_struct_init_ty,
234233 .make_ptr_const,
235234 .validate_deref,
......@@ -246,6 +245,7 @@ const Writer = struct {
246245 .bool_br_or,
247246 => try self.writeBoolBr(stream, inst),
248247
248 .validate_array_init_ty => try self.writeValidateArrayInitTy(stream, inst),
249249 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
250250 .param_type => try self.writeParamType(stream, inst),
251251 .ptr_type => try self.writePtrType(stream, inst),
......@@ -409,6 +409,7 @@ const Writer = struct {
409409 .alloc_inferred_comptime_mut,
410410 .ret_ptr,
411411 .ret_type,
412 .check_comptime_control_flow,
412413 => try self.writeNode(stream, inst),
413414
414415 .error_value,
......@@ -576,6 +577,18 @@ const Writer = struct {
576577 try self.writeSrc(stream, inst_data.src());
577578 }
578579
580 fn writeValidateArrayInitTy(
581 self: *Writer,
582 stream: anytype,
583 inst: Zir.Inst.Index,
584 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
585 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
586 const extra = self.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;
587 try self.writeInstRef(stream, extra.ty);
588 try stream.print(", {d}) ", .{extra.init_count});
589 try self.writeSrc(stream, inst_data.src());
590 }
591
579592 fn writeArrayTypeSentinel(
580593 self: *Writer,
581594 stream: anytype,
src/stage1/parser.hpp-2
......@@ -14,8 +14,6 @@
1414
1515AstNode * ast_parse(Buf *buf, ZigType *owner, ErrColor err_color);
1616
17void ast_print(AstNode *node, int indent);
18
1917void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context);
2018
2119Buf *node_identifier_buf(AstNode *node);
src/translate_c.zig+22-8
......@@ -2688,16 +2688,26 @@ fn transInitListExprVector(
26882688) TransError!Node {
26892689 _ = ty;
26902690 const qt = getExprQualType(c, @ptrCast(*const clang.Expr, expr));
2691 const vector_type = try transQualType(c, scope, qt, loc);
2691 const vector_ty = @ptrCast(*const clang.VectorType, qualTypeCanon(qt));
2692
26922693 const init_count = expr.getNumInits();
2694 const num_elements = vector_ty.getNumElements();
2695 const element_qt = vector_ty.getElementType();
26932696
26942697 if (init_count == 0) {
2695 return Tag.container_init.create(c.arena, .{
2696 .lhs = vector_type,
2697 .inits = try c.arena.alloc(ast.Payload.ContainerInit.Initializer, 0),
2698 const zero_node = try Tag.as.create(c.arena, .{
2699 .lhs = try transQualType(c, scope, element_qt, loc),
2700 .rhs = Tag.zero_literal.init(),
2701 });
2702
2703 return Tag.vector_zero_init.create(c.arena, .{
2704 .lhs = try transCreateNodeNumber(c, num_elements, .int),
2705 .rhs = zero_node,
26982706 });
26992707 }
27002708
2709 const vector_type = try transQualType(c, scope, qt, loc);
2710
27012711 var block_scope = try Scope.Block.init(c, scope, true);
27022712 defer block_scope.deinit();
27032713
......@@ -2716,11 +2726,15 @@ fn transInitListExprVector(
27162726 try block_scope.statements.append(tmp_decl_node);
27172727 }
27182728
2719 const init_list = try c.arena.alloc(Node, init_count);
2729 const init_list = try c.arena.alloc(Node, num_elements);
27202730 for (init_list) |*init, init_index| {
2721 const tmp_decl = block_scope.statements.items[init_index];
2722 const name = tmp_decl.castTag(.var_simple).?.data.name;
2723 init.* = try Tag.identifier.create(c.arena, name);
2731 if (init_index < init_count) {
2732 const tmp_decl = block_scope.statements.items[init_index];
2733 const name = tmp_decl.castTag(.var_simple).?.data.name;
2734 init.* = try Tag.identifier.create(c.arena, name);
2735 } else {
2736 init.* = Tag.undefined_literal.init();
2737 }
27242738 }
27252739
27262740 const array_init = try Tag.array_init.create(c.arena, .{
src/translate_c/ast.zig+8
......@@ -154,6 +154,8 @@ pub const Node = extern union {
154154 div_exact,
155155 /// @offsetOf(lhs, rhs)
156156 offset_of,
157 /// @splat(lhs, rhs)
158 vector_zero_init,
157159 /// @shuffle(type, a, b, mask)
158160 shuffle,
159161
......@@ -328,6 +330,7 @@ pub const Node = extern union {
328330 .div_exact,
329331 .offset_of,
330332 .helpers_cast,
333 .vector_zero_init,
331334 => Payload.BinOp,
332335
333336 .integer_literal,
......@@ -1829,6 +1832,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
18291832 const type_expr = try renderNode(c, payload.cond);
18301833 return renderArrayInit(c, type_expr, payload.cases);
18311834 },
1835 .vector_zero_init => {
1836 const payload = node.castTag(.vector_zero_init).?.data;
1837 return renderBuiltinCall(c, "@splat", &.{ payload.lhs, payload.rhs });
1838 },
18321839 .field_access => {
18331840 const payload = node.castTag(.field_access).?.data;
18341841 const lhs = try renderNodeGrouped(c, payload.lhs);
......@@ -2305,6 +2312,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
23052312 .@"struct",
23062313 .@"union",
23072314 .array_init,
2315 .vector_zero_init,
23082316 .tuple,
23092317 .container_init,
23102318 .container_init_dot,
src/type.zig+13-3
......@@ -5201,10 +5201,20 @@ pub const Type = extern union {
52015201 };
52025202 }
52035203
5204 // Works for vectors and vectors of integers.
5205 pub fn minInt(ty: Type, arena: Allocator, target: Target) !Value {
5206 const scalar = try minIntScalar(ty.scalarType(), arena, target);
5207 if (ty.zigTypeTag() == .Vector) {
5208 return Value.Tag.repeated.create(arena, scalar);
5209 } else {
5210 return scalar;
5211 }
5212 }
5213
52045214 /// Asserts that self.zigTypeTag() == .Int.
5205 pub fn minInt(self: Type, arena: Allocator, target: Target) !Value {
5206 assert(self.zigTypeTag() == .Int);
5207 const info = self.intInfo(target);
5215 pub fn minIntScalar(ty: Type, arena: Allocator, target: Target) !Value {
5216 assert(ty.zigTypeTag() == .Int);
5217 const info = ty.intInfo(target);
52085218
52095219 if (info.signedness == .unsigned) {
52105220 return Value.zero;
src/value.zig+36-15
......@@ -2292,25 +2292,13 @@ pub const Value = extern union {
22922292 }
22932293 },
22942294 .Struct => {
2295 if (ty.isTupleOrAnonStruct()) {
2296 const fields = ty.tupleFields();
2297 for (fields.values) |field_val, i| {
2298 field_val.hash(fields.types[i], hasher, mod);
2299 }
2300 return;
2301 }
2302 const fields = ty.structFields().values();
2303 if (fields.len == 0) return;
23042295 switch (val.tag()) {
2305 .empty_struct_value => {
2306 for (fields) |field| {
2307 field.default_val.hash(field.ty, hasher, mod);
2308 }
2309 },
2296 .empty_struct_value => {},
23102297 .aggregate => {
23112298 const field_values = val.castTag(.aggregate).?.data;
23122299 for (field_values) |field_val, i| {
2313 field_val.hash(fields[i].ty, hasher, mod);
2300 const field_ty = ty.structFieldType(i);
2301 field_val.hash(field_ty, hasher, mod);
23142302 }
23152303 },
23162304 else => unreachable,
......@@ -2664,6 +2652,26 @@ pub const Value = extern union {
26642652 }
26652653 }
26662654
2655 /// Returns true if a Value is backed by a variable
2656 pub fn isVariable(
2657 val: Value,
2658 mod: *Module,
2659 ) bool {
2660 return switch (val.tag()) {
2661 .slice => val.castTag(.slice).?.data.ptr.isVariable(mod),
2662 .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod),
2663 .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isVariable(mod),
2664 .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isVariable(mod),
2665 .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isVariable(mod),
2666 .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isVariable(mod),
2667 .decl_ref => mod.declPtr(val.castTag(.decl_ref).?.data).val.isVariable(mod),
2668 .decl_ref_mut => mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.isVariable(mod),
2669
2670 .variable => true,
2671 else => false,
2672 };
2673 }
2674
26672675 // Asserts that the provided start/end are in-bounds.
26682676 pub fn sliceArray(
26692677 val: Value,
......@@ -2778,6 +2786,19 @@ pub const Value = extern union {
27782786 return self.isUndef();
27792787 }
27802788
2789 /// Returns true if any value contained in `self` is undefined.
2790 /// TODO: check for cases such as array that is not marked undef but all the element
2791 /// values are marked undef, or struct that is not marked undef but all fields are marked
2792 /// undef, etc.
2793 pub fn anyUndef(self: Value) bool {
2794 if (self.castTag(.aggregate)) |aggregate| {
2795 for (aggregate.data) |val| {
2796 if (val.anyUndef()) return true;
2797 }
2798 }
2799 return self.isUndef();
2800 }
2801
27812802 /// Asserts the value is not undefined and not unreachable.
27822803 /// Integer value 0 is considered null because of C pointers.
27832804 pub fn isNull(self: Value) bool {
src/zig_clang.cpp+28
......@@ -3432,3 +3432,31 @@ const struct ZigClangAPSInt *ZigClangEnumConstantDecl_getInitVal(const struct Zi
34323432 const llvm::APSInt *result = &casted->getInitVal();
34333433 return reinterpret_cast<const ZigClangAPSInt *>(result);
34343434}
3435
3436// Get a pointer to a static variable in libc++ from LLVM and make sure that
3437// it matches our own.
3438//
3439// This check is needed because if static/dynamic linking is mixed incorrectly,
3440// it's possible for Clang and LLVM to end up with duplicate "copies" of libc++.
3441//
3442// This is not benign: Static variables are not shared, so equality comparisons
3443// that depend on pointers to static variables will fail. One such failure is
3444// std::generic_category(), which causes POSIX error codes to compare as unequal
3445// when passed between LLVM and Clang.
3446//
3447// See also: https://github.com/ziglang/zig/issues/11168
3448bool ZigClangIsLLVMUsingSeparateLibcxx() {
3449
3450 // Temporarily create an InMemoryFileSystem, so that we can perform a file
3451 // lookup that is guaranteed to fail.
3452 auto FS = new llvm::vfs::InMemoryFileSystem(true);
3453 auto StatusOrErr = FS->status("foo.txt");
3454 delete FS;
3455
3456 // This should return a POSIX (generic_category) error code, but if LLVM has
3457 // its own copy of libc++ this will actually be a separate category instance.
3458 assert(!StatusOrErr);
3459 auto EC = StatusOrErr.getError();
3460 return EC.category() != std::generic_category();
3461}
3462
src/zig_clang.h+1
......@@ -1418,4 +1418,5 @@ ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangFieldDecl_getParent(const
14181418ZIG_EXTERN_C unsigned ZigClangFieldDecl_getFieldIndex(const struct ZigClangFieldDecl *);
14191419
14201420ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangEnumConstantDecl_getInitVal(const struct ZigClangEnumConstantDecl *);
1421ZIG_EXTERN_C bool ZigClangIsLLVMUsingSeparateLibcxx();
14211422#endif
test/behavior/switch.zig-9
......@@ -53,7 +53,6 @@ test "implicit comptime switch" {
5353}
5454
5555test "switch on enum" {
56 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
5756 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5857
5958 const fruit = Fruit.Orange;
......@@ -73,7 +72,6 @@ fn nonConstSwitchOnEnum(fruit: Fruit) void {
7372}
7473
7574test "switch statement" {
76 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
7775 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7876
7977 try nonConstSwitch(SwitchStatementFoo.C);
......@@ -91,7 +89,6 @@ const SwitchStatementFoo = enum { A, B, C, D };
9189
9290test "switch with multiple expressions" {
9391 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9592 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9693
9794 const x = switch (returnsFive()) {
......@@ -120,7 +117,6 @@ fn trueIfBoolFalseOtherwise(comptime T: type) bool {
120117}
121118
122119test "switching on booleans" {
123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
124120 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
125121
126122 try testSwitchOnBools();
......@@ -218,7 +214,6 @@ fn poll() void {
218214}
219215
220216test "switch on global mutable var isn't constant-folded" {
221 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
222217 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
223218
224219 while (state < 2) {
......@@ -278,7 +273,6 @@ fn testSwitchEnumPtrCapture() !void {
278273
279274test "switch handles all cases of number" {
280275 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
281 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
282276 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
283277
284278 try testSwitchHandleAllCases();
......@@ -370,7 +364,6 @@ test "anon enum literal used in switch on union enum" {
370364}
371365
372366test "switch all prongs unreachable" {
373 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
374367 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
375368
376369 try testAllProngsUnreachable();
......@@ -582,7 +575,6 @@ test "switch on pointer type" {
582575 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
583576 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
584577 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
585 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
586578
587579 const S = struct {
588580 const X = struct {
......@@ -674,7 +666,6 @@ test "capture of integer forwards the switch condition directly" {
674666}
675667
676668test "enum value without tag name used as switch item" {
677 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
678669 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
679670
680671 const E = enum(u32) {
test/behavior/tuple.zig+35
......@@ -255,3 +255,38 @@ test "initializing anon struct with mixed comptime-runtime fields" {
255255 var a: T = .{ .foo = -1234, .bar = x + 1 };
256256 _ = a;
257257}
258
259test "tuple in tuple passed to generic function" {
260 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
261 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
262 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
263 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
264
265 const S = struct {
266 fn pair(x: f32, y: f32) std.meta.Tuple(&.{ f32, f32 }) {
267 return .{ x, y };
268 }
269
270 fn foo(x: anytype) !void {
271 try expect(x[0][0] == 1.5);
272 try expect(x[0][1] == 2.5);
273 }
274 };
275 const x = comptime S.pair(1.5, 2.5);
276 try S.foo(.{x});
277}
278
279test "coerce tuple to tuple" {
280 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
281 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
282 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
283 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
284
285 const T = std.meta.Tuple(&.{u8});
286 const S = struct {
287 fn foo(x: T) !void {
288 try expect(x[0] == 123);
289 }
290 };
291 try S.foo(.{123});
292}
test/cases/compile_errors/comptime_continue_inside_runtime_catch.zig created+16
......@@ -0,0 +1,16 @@
1export fn entry() void {
2 const ints = [_]u8{ 1, 2 };
3 inline for (ints) |_| {
4 bad() catch continue;
5 }
6}
7fn bad() !void {
8 return error.Bad;
9}
10
11// error
12// backend=stage2
13// target=native
14//
15// :4:21: error: comptime control flow inside runtime block
16// :4:15: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_if_bool.zig created+15
......@@ -0,0 +1,15 @@
1export fn entry() void {
2 var p: usize = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p == 11) continue;
6 q = false;
7 }
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :5:22: error: comptime control flow inside runtime block
15// :5:15: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_if_error.zig created+15
......@@ -0,0 +1,15 @@
1export fn entry() void {
2 var p: anyerror!i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p) |_| continue else |_| {}
6 q = false;
7 }
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :5:20: error: comptime control flow inside runtime block
15// :5:13: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_if_optional.zig created+15
......@@ -0,0 +1,15 @@
1export fn entry() void {
2 var p: ?i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p) |_| continue;
6 q = false;
7 }
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :5:20: error: comptime control flow inside runtime block
15// :5:13: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_orelse.zig created+16
......@@ -0,0 +1,16 @@
1export fn entry() void {
2 const ints = [_]u8{ 1, 2 };
3 inline for (ints) |_| {
4 bad() orelse continue;
5 }
6}
7fn bad() ?void {
8 return null;
9}
10
11// error
12// backend=stage2
13// target=native
14//
15// :4:22: error: comptime control flow inside runtime block
16// :4:15: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_switch.zig created+18
......@@ -0,0 +1,18 @@
1export fn entry() void {
2 var p: i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 switch (p) {
6 11 => continue,
7 else => {},
8 }
9 q = false;
10 }
11}
12
13// error
14// backend=stage2
15// target=native
16//
17// :6:19: error: comptime control flow inside runtime block
18// :5:17: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_while_bool.zig created+15
......@@ -0,0 +1,15 @@
1export fn entry() void {
2 var p: usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p == 11) continue :outer;
6 q = false;
7 }
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :5:25: error: comptime control flow inside runtime block
15// :5:18: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_while_error.zig created+17
......@@ -0,0 +1,17 @@
1export fn entry() void {
2 var p: anyerror!usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p) |_| {
6 continue :outer;
7 } else |_| {}
8 q = false;
9 }
10}
11
12// error
13// backend=stage2
14// target=native
15//
16// :6:13: error: comptime control flow inside runtime block
17// :5:16: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_while_optional.zig created+15
......@@ -0,0 +1,15 @@
1export fn entry() void {
2 var p: ?usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p) |_| continue :outer;
6 q = false;
7 }
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :5:23: error: comptime control flow inside runtime block
15// :5:16: note: runtime control flow here
test/cases/compile_errors/comptime_slice-sentinel_does_not_match_memory_at_target_index_terminated.zig created+74
......@@ -0,0 +1,74 @@
1export fn foo_array() void {
2 comptime {
3 var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
4 const slice = target[0..3 :0];
5 _ = slice;
6 }
7}
8export fn foo_ptr_array() void {
9 comptime {
10 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..3 :0];
13 _ = slice;
14 }
15}
16export fn foo_vector_ConstPtrSpecialBaseArray() void {
17 comptime {
18 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
19 var target: [*]u8 = &buf;
20 const slice = target[0..3 :0];
21 _ = slice;
22 }
23}
24export fn foo_vector_ConstPtrSpecialRef() void {
25 comptime {
26 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
27 var target: [*]u8 = @ptrCast([*]u8, &buf);
28 const slice = target[0..3 :0];
29 _ = slice;
30 }
31}
32export fn foo_cvector_ConstPtrSpecialBaseArray() void {
33 comptime {
34 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
35 var target: [*c]u8 = &buf;
36 const slice = target[0..3 :0];
37 _ = slice;
38 }
39}
40export fn foo_cvector_ConstPtrSpecialRef() void {
41 comptime {
42 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
43 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
44 const slice = target[0..3 :0];
45 _ = slice;
46 }
47}
48export fn foo_slice() void {
49 comptime {
50 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
51 var target: []u8 = &buf;
52 const slice = target[0..3 :0];
53 _ = slice;
54 }
55}
56
57// error
58// backend=stage2
59// target=native
60//
61// :4:29: error: value in memory does not match slice sentinel
62// :4:29: note: expected '0', found '100'
63// :12:29: error: value in memory does not match slice sentinel
64// :12:29: note: expected '0', found '100'
65// :20:29: error: value in memory does not match slice sentinel
66// :20:29: note: expected '0', found '100'
67// :28:29: error: value in memory does not match slice sentinel
68// :28:29: note: expected '0', found '100'
69// :36:29: error: value in memory does not match slice sentinel
70// :36:29: note: expected '0', found '100'
71// :44:29: error: value in memory does not match slice sentinel
72// :44:29: note: expected '0', found '100'
73// :52:29: error: value in memory does not match slice sentinel
74// :52:29: note: expected '0', found '100'
test/cases/compile_errors/comptime_slice-sentinel_does_not_match_memory_at_target_index_unterminated.zig created+74
......@@ -0,0 +1,74 @@
1export fn foo_array() void {
2 comptime {
3 var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
4 const slice = target[0..3 :0];
5 _ = slice;
6 }
7}
8export fn foo_ptr_array() void {
9 comptime {
10 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..3 :0];
13 _ = slice;
14 }
15}
16export fn foo_vector_ConstPtrSpecialBaseArray() void {
17 comptime {
18 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
19 var target: [*]u8 = &buf;
20 const slice = target[0..3 :0];
21 _ = slice;
22 }
23}
24export fn foo_vector_ConstPtrSpecialRef() void {
25 comptime {
26 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
27 var target: [*]u8 = @ptrCast([*]u8, &buf);
28 const slice = target[0..3 :0];
29 _ = slice;
30 }
31}
32export fn foo_cvector_ConstPtrSpecialBaseArray() void {
33 comptime {
34 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
35 var target: [*c]u8 = &buf;
36 const slice = target[0..3 :0];
37 _ = slice;
38 }
39}
40export fn foo_cvector_ConstPtrSpecialRef() void {
41 comptime {
42 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
43 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
44 const slice = target[0..3 :0];
45 _ = slice;
46 }
47}
48export fn foo_slice() void {
49 comptime {
50 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
51 var target: []u8 = &buf;
52 const slice = target[0..3 :0];
53 _ = slice;
54 }
55}
56
57// error
58// backend=stage2
59// target=native
60//
61// :4:29: error: value in memory does not match slice sentinel
62// :4:29: note: expected '0', found '100'
63// :12:29: error: value in memory does not match slice sentinel
64// :12:29: note: expected '0', found '100'
65// :20:29: error: value in memory does not match slice sentinel
66// :20:29: note: expected '0', found '100'
67// :28:29: error: value in memory does not match slice sentinel
68// :28:29: note: expected '0', found '100'
69// :36:29: error: value in memory does not match slice sentinel
70// :36:29: note: expected '0', found '100'
71// :44:29: error: value in memory does not match slice sentinel
72// :44:29: note: expected '0', found '100'
73// :52:29: error: value in memory does not match slice sentinel
74// :52:29: note: expected '0', found '100'
test/cases/compile_errors/comptime_slice-sentinel_does_not_match_target-sentinel.zig created+74
......@@ -0,0 +1,74 @@
1export fn foo_array() void {
2 comptime {
3 var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
4 const slice = target[0..14 :255];
5 _ = slice;
6 }
7}
8export fn foo_ptr_array() void {
9 comptime {
10 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..14 :255];
13 _ = slice;
14 }
15}
16export fn foo_vector_ConstPtrSpecialBaseArray() void {
17 comptime {
18 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
19 var target: [*]u8 = &buf;
20 const slice = target[0..14 :255];
21 _ = slice;
22 }
23}
24export fn foo_vector_ConstPtrSpecialRef() void {
25 comptime {
26 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
27 var target: [*]u8 = @ptrCast([*]u8, &buf);
28 const slice = target[0..14 :255];
29 _ = slice;
30 }
31}
32export fn foo_cvector_ConstPtrSpecialBaseArray() void {
33 comptime {
34 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
35 var target: [*c]u8 = &buf;
36 const slice = target[0..14 :255];
37 _ = slice;
38 }
39}
40export fn foo_cvector_ConstPtrSpecialRef() void {
41 comptime {
42 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
43 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
44 const slice = target[0..14 :255];
45 _ = slice;
46 }
47}
48export fn foo_slice() void {
49 comptime {
50 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
51 var target: []u8 = &buf;
52 const slice = target[0..14 :255];
53 _ = slice;
54 }
55}
56
57// error
58// backend=stage2
59// target=native
60//
61// :4:29: error: value in memory does not match slice sentinel
62// :4:29: note: expected '255', found '0'
63// :12:29: error: value in memory does not match slice sentinel
64// :12:29: note: expected '255', found '0'
65// :20:29: error: value in memory does not match slice sentinel
66// :20:29: note: expected '255', found '0'
67// :28:29: error: value in memory does not match slice sentinel
68// :28:29: note: expected '255', found '0'
69// :36:29: error: value in memory does not match slice sentinel
70// :36:29: note: expected '255', found '0'
71// :44:29: error: value in memory does not match slice sentinel
72// :44:29: note: expected '255', found '0'
73// :52:29: error: value in memory does not match slice sentinel
74// :52:29: note: expected '255', found '0'
test/cases/compile_errors/comptime_slice-sentinel_is_out_of_bounds_terminated.zig created+67
......@@ -0,0 +1,67 @@
1export fn foo_array() void {
2 comptime {
3 var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
4 const slice = target[0..15 :1];
5 _ = slice;
6 }
7}
8export fn foo_ptr_array() void {
9 comptime {
10 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..15 :0];
13 _ = slice;
14 }
15}
16export fn foo_vector_ConstPtrSpecialBaseArray() void {
17 comptime {
18 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
19 var target: [*]u8 = &buf;
20 const slice = target[0..15 :0];
21 _ = slice;
22 }
23}
24export fn foo_vector_ConstPtrSpecialRef() void {
25 comptime {
26 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
27 var target: [*]u8 = @ptrCast([*]u8, &buf);
28 const slice = target[0..15 :0];
29 _ = slice;
30 }
31}
32export fn foo_cvector_ConstPtrSpecialBaseArray() void {
33 comptime {
34 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
35 var target: [*c]u8 = &buf;
36 const slice = target[0..15 :0];
37 _ = slice;
38 }
39}
40export fn foo_cvector_ConstPtrSpecialRef() void {
41 comptime {
42 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
43 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
44 const slice = target[0..15 :0];
45 _ = slice;
46 }
47}
48export fn foo_slice() void {
49 comptime {
50 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
51 var target: []u8 = &buf;
52 const slice = target[0..15 :0];
53 _ = slice;
54 }
55}
56
57// error
58// backend=stage2
59// target=native
60//
61// :4:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8'
62// :12:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8'
63// :20:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8'
64// :28:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8'
65// :36:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8'
66// :44:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8'
67// :52:33: error: end index 15 out of bounds for slice of length 14
test/cases/compile_errors/comptime_slice-sentinel_is_out_of_bounds_unterminated.zig created+67
......@@ -0,0 +1,67 @@
1export fn foo_array() void {
2 comptime {
3 var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
4 const slice = target[0..14 :0];
5 _ = slice;
6 }
7}
8export fn foo_ptr_array() void {
9 comptime {
10 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..14 :0];
13 _ = slice;
14 }
15}
16export fn foo_vector_ConstPtrSpecialBaseArray() void {
17 comptime {
18 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
19 var target: [*]u8 = &buf;
20 const slice = target[0..14 :0];
21 _ = slice;
22 }
23}
24export fn foo_vector_ConstPtrSpecialRef() void {
25 comptime {
26 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
27 var target: [*]u8 = @ptrCast([*]u8, &buf);
28 const slice = target[0..14 :0];
29 _ = slice;
30 }
31}
32export fn foo_cvector_ConstPtrSpecialBaseArray() void {
33 comptime {
34 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
35 var target: [*c]u8 = &buf;
36 const slice = target[0..14 :0];
37 _ = slice;
38 }
39}
40export fn foo_cvector_ConstPtrSpecialRef() void {
41 comptime {
42 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
43 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
44 const slice = target[0..14 :0];
45 _ = slice;
46 }
47}
48export fn foo_slice() void {
49 comptime {
50 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
51 var target: []u8 = &buf;
52 const slice = target[0..14 :0];
53 _ = slice;
54 }
55}
56
57// error
58// backend=stage2
59// target=native
60//
61// :4:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8'
62// :12:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8'
63// :20:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8'
64// :28:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8'
65// :36:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8'
66// :44:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8'
67// :52:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8'
test/cases/compile_errors/comptime_slice_of_an_undefined_slice.zig created+11
......@@ -0,0 +1,11 @@
1comptime {
2 var a: []u8 = undefined;
3 var b = a[0..10];
4 _ = b;
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :3:14: error: slice of undefined
test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig+3-3
......@@ -3,14 +3,14 @@ pub const List = struct {
33 allocator: *Allocator,
44
55 pub fn init(allocator: *Allocator) List {
6 return List {
6 return List{
77 .len = 0,
88 .allocator = allocator,
99 };
1010 }
1111};
1212
13pub var global_allocator = Allocator {
13pub var global_allocator = Allocator{
1414 .field = 1234,
1515};
1616
......@@ -28,4 +28,4 @@ export fn foo() void {
2828// target=native
2929//
3030// :23:6: error: no field or member function named 'init' in 'tmp.List'
31// :1:14: note: struct declared here
31// :1:18: note: struct declared here
test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig created+17
......@@ -0,0 +1,17 @@
1const Foo = @Type(.{
2 .Fn = .{
3 .calling_convention = .Unspecified,
4 .alignment = 0,
5 .is_generic = true,
6 .is_var_args = false,
7 .return_type = u0,
8 .args = &.{},
9 },
10});
11comptime { _ = Foo; }
12
13// error
14// backend=stage2
15// target=native
16//
17// :1:13: error: Type.Fn.is_generic must be false for @Type
test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig created+17
......@@ -0,0 +1,17 @@
1const Foo = @Type(.{
2 .Fn = .{
3 .calling_convention = .Unspecified,
4 .alignment = 0,
5 .is_generic = false,
6 .is_var_args = true,
7 .return_type = u0,
8 .args = &.{},
9 },
10});
11comptime { _ = Foo; }
12
13// error
14// backend=stage2
15// target=native
16//
17// :1:13: error: varargs functions must have C calling convention
test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig created+17
......@@ -0,0 +1,17 @@
1const Foo = @Type(.{
2 .Fn = .{
3 .calling_convention = .Unspecified,
4 .alignment = 0,
5 .is_generic = false,
6 .is_var_args = false,
7 .return_type = null,
8 .args = &.{},
9 },
10});
11comptime { _ = Foo; }
12
13// error
14// backend=stage2
15// target=native
16//
17// :1:13: error: Type.Fn.return_type must be non-null for @Type
test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig created+18
......@@ -0,0 +1,18 @@
1const Tag = @Type(.{
2 .Enum = .{
3 .layout = .Auto,
4 .tag_type = bool,
5 .fields = &.{},
6 .decls = &.{},
7 .is_exhaustive = false,
8 },
9});
10export fn entry() void {
11 _ = @intToEnum(Tag, 0);
12}
13
14// error
15// backend=stage2
16// target=native
17//
18// :1:13: error: Type.Enum.tag_type must be an integer type
test/cases/compile_errors/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig created+18
......@@ -0,0 +1,18 @@
1const Tag = @Type(.{
2 .Enum = .{
3 .layout = .Auto,
4 .tag_type = undefined,
5 .fields = &.{},
6 .decls = &.{},
7 .is_exhaustive = false,
8 },
9});
10export fn entry() void {
11 _ = @intToEnum(Tag, 0);
12}
13
14// error
15// backend=stage2
16// target=native
17//
18// :1:13: error: use of undefined value here causes undefined behavior
test/cases/compile_errors/reify_type_for_exhaustive_enum_with_zero_fields.zig created+18
......@@ -0,0 +1,18 @@
1const Tag = @Type(.{
2 .Enum = .{
3 .layout = .Auto,
4 .tag_type = u1,
5 .fields = &.{},
6 .decls = &.{},
7 .is_exhaustive = true,
8 },
9});
10export fn entry() void {
11 _ = @intToEnum(Tag, 0);
12}
13
14// error
15// backend=stage2
16// target=native
17//
18// :1:13: error: enums must have at least one field
test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig created+36
......@@ -0,0 +1,36 @@
1const Tag = @Type(.{
2 .Enum = .{
3 .layout = .Auto,
4 .tag_type = u2,
5 .fields = &.{
6 .{ .name = "signed", .value = 0 },
7 .{ .name = "unsigned", .value = 1 },
8 .{ .name = "arst", .value = 2 },
9 },
10 .decls = &.{},
11 .is_exhaustive = true,
12 },
13});
14const Tagged = @Type(.{
15 .Union = .{
16 .layout = .Auto,
17 .tag_type = Tag,
18 .fields = &.{
19 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
20 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
21 },
22 .decls = &.{},
23 },
24});
25export fn entry() void {
26 var tagged = Tagged{ .signed = -1 };
27 tagged = .{ .unsigned = 1 };
28}
29
30// error
31// backend=stage2
32// target=native
33//
34// :14:16: error: enum field(s) missing in union
35// :1:13: note: field 'arst' missing, declared here
36// :1:13: note: enum declared here
test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig created+35
......@@ -0,0 +1,35 @@
1const Tag = @Type(.{
2 .Enum = .{
3 .layout = .Auto,
4 .tag_type = u1,
5 .fields = &.{
6 .{ .name = "signed", .value = 0 },
7 .{ .name = "unsigned", .value = 1 },
8 },
9 .decls = &.{},
10 .is_exhaustive = true,
11 },
12});
13const Tagged = @Type(.{
14 .Union = .{
15 .layout = .Auto,
16 .tag_type = Tag,
17 .fields = &.{
18 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
19 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
20 .{ .name = "arst", .field_type = f32, .alignment = @alignOf(f32) },
21 },
22 .decls = &.{},
23 },
24});
25export fn entry() void {
26 var tagged = Tagged{ .signed = -1 };
27 tagged = .{ .unsigned = 1 };
28}
29
30// error
31// backend=stage2
32// target=native
33//
34// :13:16: error: no field named 'arst' in enum 'tmp.Tag__enum_264'
35// :1:13: note: enum declared here
test/cases/compile_errors/reify_type_for_union_with_zero_fields.zig created+17
......@@ -0,0 +1,17 @@
1const Untagged = @Type(.{
2 .Union = .{
3 .layout = .Auto,
4 .tag_type = null,
5 .fields = &.{},
6 .decls = &.{},
7 },
8});
9export fn entry() void {
10 _ = Untagged{};
11}
12
13// error
14// backend=stage2
15// target=native
16//
17// :1:18: error: unions must have at least one field
test/cases/compile_errors/reify_type_union_payload_is_undefined.zig created+10
......@@ -0,0 +1,10 @@
1const Foo = @Type(.{
2 .Struct = undefined,
3});
4comptime { _ = Foo; }
5
6// error
7// backend=stage2
8// target=native
9//
10// :1:13: error: use of undefined value here causes undefined behavior
test/cases/compile_errors/reify_type_with_Type.Int.zig created+15
......@@ -0,0 +1,15 @@
1const builtin = @import("std").builtin;
2export fn entry() void {
3 _ = @Type(builtin.Type.Int{
4 .signedness = .signed,
5 .bits = 8,
6 });
7}
8
9// error
10// backend=stage2
11// target=native
12//
13// :3:31: error: expected type 'builtin.Type', found 'builtin.Type.Int'
14// :?:?: note: struct declared here
15// :?:?: note: union declared here
test/cases/compile_errors/reify_type_with_undefined.zig created+20
......@@ -0,0 +1,20 @@
1comptime {
2 _ = @Type(.{ .Array = .{ .len = 0, .child = u8, .sentinel = undefined } });
3}
4comptime {
5 _ = @Type(.{
6 .Struct = .{
7 .fields = undefined,
8 .decls = undefined,
9 .is_tuple = false,
10 .layout = .Auto,
11 },
12 });
13}
14
15// error
16// backend=stage2
17// target=native
18//
19// :2:9: error: use of undefined value here causes undefined behavior
20// :5:9: error: use of undefined value here causes undefined behavior
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_catch.zig deleted-16
......@@ -1,16 +0,0 @@
1export fn entry() void {
2 const ints = [_]u8{ 1, 2 };
3 inline for (ints) |_| {
4 bad() catch continue;
5 }
6}
7fn bad() !void {
8 return error.Bad;
9}
10
11// error
12// backend=stage1
13// target=native
14//
15// tmp.zig:4:21: error: comptime control flow inside runtime block
16// tmp.zig:4:15: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_bool.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 var p: usize = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p == 11) continue;
6 q = false;
7 }
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:5:22: error: comptime control flow inside runtime block
15// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_error.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 var p: anyerror!i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p) |_| continue else |_| {}
6 q = false;
7 }
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:5:20: error: comptime control flow inside runtime block
15// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_optional.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 var p: ?i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p) |_| continue;
6 q = false;
7 }
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:5:20: error: comptime control flow inside runtime block
15// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_switch.zig deleted-18
......@@ -1,18 +0,0 @@
1export fn entry() void {
2 var p: i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 switch (p) {
6 11 => continue,
7 else => {},
8 }
9 q = false;
10 }
11}
12
13// error
14// backend=stage1
15// target=native
16//
17// tmp.zig:6:19: error: comptime control flow inside runtime block
18// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_bool.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 var p: usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p == 11) continue :outer;
6 q = false;
7 }
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:5:25: error: comptime control flow inside runtime block
15// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_error.zig deleted-17
......@@ -1,17 +0,0 @@
1export fn entry() void {
2 var p: anyerror!usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p) |_| {
6 continue :outer;
7 } else |_| {}
8 q = false;
9 }
10}
11
12// error
13// backend=stage1
14// target=native
15//
16// tmp.zig:6:13: error: comptime control flow inside runtime block
17// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_optional.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 var p: ?usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p) |_| continue :outer;
6 q = false;
7 }
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:5:23: error: comptime control flow inside runtime block
15// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_memory_at_target_index_terminated.zig deleted-67
......@@ -1,67 +0,0 @@
1export fn foo_array() void {
2 comptime {
3 var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
4 const slice = target[0..3 :0];
5 _ = slice;
6 }
7}
8export fn foo_ptr_array() void {
9 comptime {
10 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..3 :0];
13 _ = slice;
14 }
15}
16export fn foo_vector_ConstPtrSpecialBaseArray() void {
17 comptime {
18 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
19 var target: [*]u8 = &buf;
20 const slice = target[0..3 :0];
21 _ = slice;
22 }
23}
24export fn foo_vector_ConstPtrSpecialRef() void {
25 comptime {
26 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
27 var target: [*]u8 = @ptrCast([*]u8, &buf);
28 const slice = target[0..3 :0];
29 _ = slice;
30 }
31}
32export fn foo_cvector_ConstPtrSpecialBaseArray() void {
33 comptime {
34 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
35 var target: [*c]u8 = &buf;
36 const slice = target[0..3 :0];
37 _ = slice;
38 }
39}
40export fn foo_cvector_ConstPtrSpecialRef() void {
41 comptime {
42 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
43 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
44 const slice = target[0..3 :0];
45 _ = slice;
46 }
47}
48export fn foo_slice() void {
49 comptime {
50 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
51 var target: []u8 = &buf;
52 const slice = target[0..3 :0];
53 _ = slice;
54 }
55}
56
57// error
58// backend=stage1
59// target=native
60//
61// :4:29: error: slice-sentinel does not match memory at target index
62// :12:29: error: slice-sentinel does not match memory at target index
63// :20:29: error: slice-sentinel does not match memory at target index
64// :28:29: error: slice-sentinel does not match memory at target index
65// :36:29: error: slice-sentinel does not match memory at target index
66// :44:29: error: slice-sentinel does not match memory at target index
67// :52:29: error: slice-sentinel does not match memory at target index
test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_memory_at_target_index_unterminated.zig deleted-67
......@@ -1,67 +0,0 @@
1export fn foo_array() void {
2 comptime {
3 var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
4 const slice = target[0..3 :0];
5 _ = slice;
6 }
7}
8export fn foo_ptr_array() void {
9 comptime {
10 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..3 :0];
13 _ = slice;
14 }
15}
16export fn foo_vector_ConstPtrSpecialBaseArray() void {
17 comptime {
18 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
19 var target: [*]u8 = &buf;
20 const slice = target[0..3 :0];
21 _ = slice;
22 }
23}
24export fn foo_vector_ConstPtrSpecialRef() void {
25 comptime {
26 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
27 var target: [*]u8 = @ptrCast([*]u8, &buf);
28 const slice = target[0..3 :0];
29 _ = slice;
30 }
31}
32export fn foo_cvector_ConstPtrSpecialBaseArray() void {
33 comptime {
34 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
35 var target: [*c]u8 = &buf;
36 const slice = target[0..3 :0];
37 _ = slice;
38 }
39}
40export fn foo_cvector_ConstPtrSpecialRef() void {
41 comptime {
42 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
43 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
44 const slice = target[0..3 :0];
45 _ = slice;
46 }
47}
48export fn foo_slice() void {
49 comptime {
50 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
51 var target: []u8 = &buf;
52 const slice = target[0..3 :0];
53 _ = slice;
54 }
55}
56
57// error
58// backend=stage1
59// target=native
60//
61// :4:29: error: slice-sentinel does not match memory at target index
62// :12:29: error: slice-sentinel does not match memory at target index
63// :20:29: error: slice-sentinel does not match memory at target index
64// :28:29: error: slice-sentinel does not match memory at target index
65// :36:29: error: slice-sentinel does not match memory at target index
66// :44:29: error: slice-sentinel does not match memory at target index
67// :52:29: error: slice-sentinel does not match memory at target index
test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_target-sentinel.zig deleted-67
......@@ -1,67 +0,0 @@
1export fn foo_array() void {
2 comptime {
3 var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
4 const slice = target[0..14 :255];
5 _ = slice;
6 }
7}
8export fn foo_ptr_array() void {
9 comptime {
10 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..14 :255];
13 _ = slice;
14 }
15}
16export fn foo_vector_ConstPtrSpecialBaseArray() void {
17 comptime {
18 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
19 var target: [*]u8 = &buf;
20 const slice = target[0..14 :255];
21 _ = slice;
22 }
23}
24export fn foo_vector_ConstPtrSpecialRef() void {
25 comptime {
26 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
27 var target: [*]u8 = @ptrCast([*]u8, &buf);
28 const slice = target[0..14 :255];
29 _ = slice;
30 }
31}
32export fn foo_cvector_ConstPtrSpecialBaseArray() void {
33 comptime {
34 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
35 var target: [*c]u8 = &buf;
36 const slice = target[0..14 :255];
37 _ = slice;
38 }
39}
40export fn foo_cvector_ConstPtrSpecialRef() void {
41 comptime {
42 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
43 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
44 const slice = target[0..14 :255];
45 _ = slice;
46 }
47}
48export fn foo_slice() void {
49 comptime {
50 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
51 var target: []u8 = &buf;
52 const slice = target[0..14 :255];
53 _ = slice;
54 }
55}
56
57// error
58// backend=stage1
59// target=native
60//
61// :4:29: error: slice-sentinel does not match target-sentinel
62// :12:29: error: slice-sentinel does not match target-sentinel
63// :20:29: error: slice-sentinel does not match target-sentinel
64// :28:29: error: slice-sentinel does not match target-sentinel
65// :36:29: error: slice-sentinel does not match target-sentinel
66// :44:29: error: slice-sentinel does not match target-sentinel
67// :52:29: error: slice-sentinel does not match target-sentinel
test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_is_out_of_bounds_terminated.zig deleted-67
......@@ -1,67 +0,0 @@
1export fn foo_array() void {
2 comptime {
3 var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
4 const slice = target[0..15 :1];
5 _ = slice;
6 }
7}
8export fn foo_ptr_array() void {
9 comptime {
10 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..15 :0];
13 _ = slice;
14 }
15}
16export fn foo_vector_ConstPtrSpecialBaseArray() void {
17 comptime {
18 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
19 var target: [*]u8 = &buf;
20 const slice = target[0..15 :0];
21 _ = slice;
22 }
23}
24export fn foo_vector_ConstPtrSpecialRef() void {
25 comptime {
26 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
27 var target: [*]u8 = @ptrCast([*]u8, &buf);
28 const slice = target[0..15 :0];
29 _ = slice;
30 }
31}
32export fn foo_cvector_ConstPtrSpecialBaseArray() void {
33 comptime {
34 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
35 var target: [*c]u8 = &buf;
36 const slice = target[0..15 :0];
37 _ = slice;
38 }
39}
40export fn foo_cvector_ConstPtrSpecialRef() void {
41 comptime {
42 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
43 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
44 const slice = target[0..15 :0];
45 _ = slice;
46 }
47}
48export fn foo_slice() void {
49 comptime {
50 var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
51 var target: []u8 = &buf;
52 const slice = target[0..15 :0];
53 _ = slice;
54 }
55}
56
57// error
58// backend=stage1
59// target=native
60//
61// :4:29: error: out of bounds slice
62// :12:29: error: out of bounds slice
63// :20:29: error: out of bounds slice
64// :28:29: error: out of bounds slice
65// :36:29: error: out of bounds slice
66// :44:29: error: out of bounds slice
67// :52:29: error: out of bounds slice
test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_is_out_of_bounds_unterminated.zig deleted-67
......@@ -1,67 +0,0 @@
1export fn foo_array() void {
2 comptime {
3 var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
4 const slice = target[0..14 :0];
5 _ = slice;
6 }
7}
8export fn foo_ptr_array() void {
9 comptime {
10 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
11 var target = &buf;
12 const slice = target[0..14 :0];
13 _ = slice;
14 }
15}
16export fn foo_vector_ConstPtrSpecialBaseArray() void {
17 comptime {
18 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
19 var target: [*]u8 = &buf;
20 const slice = target[0..14 :0];
21 _ = slice;
22 }
23}
24export fn foo_vector_ConstPtrSpecialRef() void {
25 comptime {
26 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
27 var target: [*]u8 = @ptrCast([*]u8, &buf);
28 const slice = target[0..14 :0];
29 _ = slice;
30 }
31}
32export fn foo_cvector_ConstPtrSpecialBaseArray() void {
33 comptime {
34 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
35 var target: [*c]u8 = &buf;
36 const slice = target[0..14 :0];
37 _ = slice;
38 }
39}
40export fn foo_cvector_ConstPtrSpecialRef() void {
41 comptime {
42 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
43 var target: [*c]u8 = @ptrCast([*c]u8, &buf);
44 const slice = target[0..14 :0];
45 _ = slice;
46 }
47}
48export fn foo_slice() void {
49 comptime {
50 var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10;
51 var target: []u8 = &buf;
52 const slice = target[0..14 :0];
53 _ = slice;
54 }
55}
56
57// error
58// backend=stage1
59// target=native
60//
61// :4:29: error: slice-sentinel is out of bounds
62// :12:29: error: slice-sentinel is out of bounds
63// :20:29: error: slice-sentinel is out of bounds
64// :28:29: error: slice-sentinel is out of bounds
65// :36:29: error: slice-sentinel is out of bounds
66// :44:29: error: slice-sentinel is out of bounds
67// :52:29: error: slice-sentinel is out of bounds
test/cases/compile_errors/stage1/obj/comptime_slice_of_an_undefined_slice.zig deleted-11
......@@ -1,11 +0,0 @@
1comptime {
2 var a: []u8 = undefined;
3 var b = a[0..10];
4 _ = b;
5}
6
7// error
8// backend=stage1
9// target=native
10//
11// tmp.zig:3:14: error: slice of undefined
test/cases/compile_errors/stage1/obj/reify_type.Fn_with_is_generic_true.zig deleted-17
......@@ -1,17 +0,0 @@
1const Foo = @Type(.{
2 .Fn = .{
3 .calling_convention = .Unspecified,
4 .alignment = 0,
5 .is_generic = true,
6 .is_var_args = false,
7 .return_type = u0,
8 .args = &.{},
9 },
10});
11comptime { _ = Foo; }
12
13// error
14// backend=stage1
15// target=native
16//
17// tmp.zig:1:20: error: Type.Fn.is_generic must be false for @Type
test/cases/compile_errors/stage1/obj/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig deleted-17
......@@ -1,17 +0,0 @@
1const Foo = @Type(.{
2 .Fn = .{
3 .calling_convention = .Unspecified,
4 .alignment = 0,
5 .is_generic = false,
6 .is_var_args = true,
7 .return_type = u0,
8 .args = &.{},
9 },
10});
11comptime { _ = Foo; }
12
13// error
14// backend=stage1
15// target=native
16//
17// tmp.zig:1:20: error: varargs functions must have C calling convention
test/cases/compile_errors/stage1/obj/reify_type.Fn_with_return_type_null.zig deleted-17
......@@ -1,17 +0,0 @@
1const Foo = @Type(.{
2 .Fn = .{
3 .calling_convention = .Unspecified,
4 .alignment = 0,
5 .is_generic = false,
6 .is_var_args = false,
7 .return_type = null,
8 .args = &.{},
9 },
10});
11comptime { _ = Foo; }
12
13// error
14// backend=stage1
15// target=native
16//
17// tmp.zig:1:20: error: Type.Fn.return_type must be non-null for @Type
test/cases/compile_errors/stage1/obj/reify_type.Pointer_with_invalid_address_space.zig deleted-18
......@@ -1,18 +0,0 @@
1export fn entry() void {
2 _ = @Type(.{ .Pointer = .{
3 .size = .One,
4 .is_const = false,
5 .is_volatile = false,
6 .alignment = 1,
7 .address_space = .gs,
8 .child = u8,
9 .is_allowzero = false,
10 .sentinel = null,
11 }});
12}
13
14// error
15// backend=stage1
16// target=native
17//
18// tmp.zig:2:16: error: address space 'gs' not available in stage 1 compiler, must be .generic
test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig deleted-18
......@@ -1,18 +0,0 @@
1const Tag = @Type(.{
2 .Enum = .{
3 .layout = .Auto,
4 .tag_type = bool,
5 .fields = &.{},
6 .decls = &.{},
7 .is_exhaustive = false,
8 },
9});
10export fn entry() void {
11 _ = @intToEnum(Tag, 0);
12}
13
14// error
15// backend=stage1
16// target=native
17//
18// tmp.zig:1:20: error: Type.Enum.tag_type must be an integer type, not 'bool'
test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig deleted-18
......@@ -1,18 +0,0 @@
1const Tag = @Type(.{
2 .Enum = .{
3 .layout = .Auto,
4 .tag_type = undefined,
5 .fields = &.{},
6 .decls = &.{},
7 .is_exhaustive = false,
8 },
9});
10export fn entry() void {
11 _ = @intToEnum(Tag, 0);
12}
13
14// error
15// backend=stage1
16// target=native
17//
18// tmp.zig:1:20: error: use of undefined value here causes undefined behavior
test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_zero_fields.zig deleted-18
......@@ -1,18 +0,0 @@
1const Tag = @Type(.{
2 .Enum = .{
3 .layout = .Auto,
4 .tag_type = u1,
5 .fields = &.{},
6 .decls = &.{},
7 .is_exhaustive = true,
8 },
9});
10export fn entry() void {
11 _ = @intToEnum(Tag, 0);
12}
13
14// error
15// backend=stage1
16// target=native
17//
18// tmp.zig:1:20: error: enums must have 1 or more fields
test/cases/compile_errors/stage1/obj/reify_type_for_tagged_union_with_extra_enum_field.zig deleted-34
......@@ -1,34 +0,0 @@
1const Tag = @Type(.{
2 .Enum = .{
3 .layout = .Auto,
4 .tag_type = u2,
5 .fields = &.{
6 .{ .name = "signed", .value = 0 },
7 .{ .name = "unsigned", .value = 1 },
8 .{ .name = "arst", .value = 2 },
9 },
10 .decls = &.{},
11 .is_exhaustive = true,
12 },
13});
14const Tagged = @Type(.{
15 .Union = .{
16 .layout = .Auto,
17 .tag_type = Tag,
18 .fields = &.{
19 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
20 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
21 },
22 .decls = &.{},
23 },
24});
25export fn entry() void {
26 var tagged = Tagged{ .signed = -1 };
27 tagged = .{ .unsigned = 1 };
28}
29
30// error
31// backend=stage1
32// target=native
33//
34// tmp.zig:14:23: error: enum field missing: 'arst'
test/cases/compile_errors/stage1/obj/reify_type_for_tagged_union_with_extra_union_field.zig deleted-35
......@@ -1,35 +0,0 @@
1const Tag = @Type(.{
2 .Enum = .{
3 .layout = .Auto,
4 .tag_type = u1,
5 .fields = &.{
6 .{ .name = "signed", .value = 0 },
7 .{ .name = "unsigned", .value = 1 },
8 },
9 .decls = &.{},
10 .is_exhaustive = true,
11 },
12});
13const Tagged = @Type(.{
14 .Union = .{
15 .layout = .Auto,
16 .tag_type = Tag,
17 .fields = &.{
18 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
19 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
20 .{ .name = "arst", .field_type = f32, .alignment = @alignOf(f32) },
21 },
22 .decls = &.{},
23 },
24});
25export fn entry() void {
26 var tagged = Tagged{ .signed = -1 };
27 tagged = .{ .unsigned = 1 };
28}
29
30// error
31// backend=stage1
32// target=native
33//
34// tmp.zig:13:23: error: enum field not found: 'arst'
35// tmp.zig:1:20: note: enum declared here
test/cases/compile_errors/stage1/obj/reify_type_for_union_with_zero_fields.zig deleted-17
......@@ -1,17 +0,0 @@
1const Untagged = @Type(.{
2 .Union = .{
3 .layout = .Auto,
4 .tag_type = null,
5 .fields = &.{},
6 .decls = &.{},
7 },
8});
9export fn entry() void {
10 _ = Untagged{};
11}
12
13// error
14// backend=stage1
15// target=native
16//
17// tmp.zig:1:25: error: unions must have 1 or more fields
test/cases/compile_errors/stage1/obj/reify_type_union_payload_is_undefined.zig deleted-10
......@@ -1,10 +0,0 @@
1const Foo = @Type(.{
2 .Struct = undefined,
3});
4comptime { _ = Foo; }
5
6// error
7// backend=stage1
8// target=native
9//
10// tmp.zig:1:20: error: use of undefined value here causes undefined behavior
test/cases/compile_errors/stage1/obj/reify_type_with_Type.Int.zig deleted-13
......@@ -1,13 +0,0 @@
1const builtin = @import("std").builtin;
2export fn entry() void {
3 _ = @Type(builtin.Type.Int{
4 .signedness = .signed,
5 .bits = 8,
6 });
7}
8
9// error
10// backend=stage1
11// target=native
12//
13// tmp.zig:3:31: error: expected type 'std.builtin.Type', found 'std.builtin.Type.Int'
test/cases/compile_errors/stage1/obj/reify_type_with_non-constant_expression.zig deleted-11
......@@ -1,11 +0,0 @@
1const builtin = @import("std").builtin;
2var globalTypeInfo : builtin.Type = undefined;
3export fn entry() void {
4 _ = @Type(globalTypeInfo);
5}
6
7// error
8// backend=stage1
9// target=native
10//
11// tmp.zig:4:15: error: unable to evaluate constant expression
test/cases/compile_errors/stage1/obj/reify_type_with_undefined.zig deleted-20
......@@ -1,20 +0,0 @@
1comptime {
2 _ = @Type(.{ .Array = .{ .len = 0, .child = u8, .sentinel = undefined } });
3}
4comptime {
5 _ = @Type(.{
6 .Struct = .{
7 .fields = undefined,
8 .decls = undefined,
9 .is_tuple = false,
10 .layout = .Auto,
11 },
12 });
13}
14
15// error
16// backend=stage1
17// target=native
18//
19// tmp.zig:2:16: error: use of undefined value here causes undefined behavior
20// tmp.zig:5:16: error: use of undefined value here causes undefined behavior
test/cases/compile_errors/stage1/reify_type.Pointer_with_invalid_address_space.zig created+18
......@@ -0,0 +1,18 @@
1export fn entry() void {
2 _ = @Type(.{ .Pointer = .{
3 .size = .One,
4 .is_const = false,
5 .is_volatile = false,
6 .alignment = 1,
7 .address_space = .gs,
8 .child = u8,
9 .is_allowzero = false,
10 .sentinel = null,
11 }});
12}
13
14// error
15// backend=stage1
16// target=native
17//
18// tmp.zig:2:16: error: address space 'gs' not available in stage 1 compiler, must be .generic
test/cases/compile_errors/stage1/reify_type_with_non-constant_expression.zig created+11
......@@ -0,0 +1,11 @@
1const builtin = @import("std").builtin;
2var globalTypeInfo : builtin.Type = undefined;
3export fn entry() void {
4 _ = @Type(globalTypeInfo);
5}
6
7// error
8// backend=stage1
9// target=native
10//
11// tmp.zig:4:15: error: unable to evaluate constant expression
test/cases/compile_errors/stage1/test/type_mismatch_with_tuple_concatenation.zig deleted-11
......@@ -1,11 +0,0 @@
1export fn entry() void {
2 var x = .{};
3 x = x ++ .{ 1, 2, 3 };
4}
5
6// error
7// backend=stage1
8// target=native
9// is_test=1
10//
11// tmp.zig:3:11: error: expected type 'struct:2:14', found 'struct:3:11'
test/cases/compile_errors/tuple_init_edge_cases.zig created+44
......@@ -0,0 +1,44 @@
1pub export fn entry1() void {
2 const T = @TypeOf(.{ 123, 3 });
3 var b = T{ .@"1" = 3 }; _ = b;
4 var c = T{ 123, 3 }; _ = c;
5 var d = T{}; _ = d;
6}
7pub export fn entry2() void {
8 var a: u32 = 2;
9 const T = @TypeOf(.{ 123, a });
10 var b = T{ .@"1" = 3 }; _ = b;
11 var c = T{ 123, 3 }; _ = c;
12 var d = T{}; _ = d;
13}
14pub export fn entry3() void {
15 var a: u32 = 2;
16 const T = @TypeOf(.{ 123, a });
17 var b = T{ .@"0" = 123 }; _ = b;
18}
19comptime {
20 var a: u32 = 2;
21 const T = @TypeOf(.{ 123, a });
22 var b = T{ .@"0" = 123 }; _ = b;
23 var c = T{ 123, 2 }; _ = c;
24 var d = T{}; _ = d;
25}
26pub export fn entry4() void {
27 var a: u32 = 2;
28 const T = @TypeOf(.{ 123, a });
29 var b = T{ 123, 4, 5 }; _ = b;
30}
31pub export fn entry5() void {
32 var a: u32 = 2;
33 const T = @TypeOf(.{ 123, a });
34 var b = T{ .@"0" = 123, .@"2" = 123, .@"1" = 123 }; _ = b;
35}
36
37// error
38// backend=stage2
39// target=native
40//
41// :12:14: error: missing tuple field with index 1
42// :17:14: error: missing tuple field with index 1
43// :29:14: error: expected at most 2 tuple fields; found 3
44// :34:30: error: index '2' out of bounds of tuple 'tuple{comptime comptime_int = 123, u32}'
test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig created+10
......@@ -0,0 +1,10 @@
1export fn entry() void {
2 var x = .{};
3 x = x ++ .{ 1, 2, 3 };
4}
5
6// error
7// backend=stage2
8// target=native
9//
10// :3:11: error: index '0' out of bounds of tuple '@TypeOf(.{})'
test/cases/compile_errors/wrong_size_to_an_array_literal.zig+1-1
......@@ -7,4 +7,4 @@ comptime {
77// backend=stage2
88// target=native
99//
10// :2:31: error: index 2 outside array of length 2
10// :2:24: error: expected 2 array elements; found 3
test/cases/llvm/shift_right_plus_left.0.zig deleted-12
......@@ -1,12 +0,0 @@
1pub fn main() void {
2 var i: u32 = 16;
3 assert(i >> 1, 8);
4}
5fn assert(a: u32, b: u32) void {
6 if (a != b) unreachable;
7}
8
9// run
10// backend=llvm
11// target=x86_64-linux,x86_64-macos
12//
test/cases/llvm/shift_right_plus_left.1.zig deleted-10
......@@ -1,10 +0,0 @@
1pub fn main() void {
2 var i: u32 = 16;
3 assert(i << 1, 32);
4}
5fn assert(a: u32, b: u32) void {
6 if (a != b) unreachable;
7}
8
9// run
10//
test/run_translated_c.zig+22-22
......@@ -1322,28 +1322,28 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
13221322 \\}
13231323 , "");
13241324
1325 if (@import("builtin").zig_backend == .stage1) {
1326 // https://github.com/ziglang/zig/issues/12264
1327 cases.add("basic vector expressions",
1328 \\#include <stdlib.h>
1329 \\#include <stdint.h>
1330 \\typedef int16_t __v8hi __attribute__((__vector_size__(16)));
1331 \\int main(int argc, char**argv) {
1332 \\ __v8hi uninitialized;
1333 \\ __v8hi empty_init = {};
1334 \\ __v8hi partial_init = {0, 1, 2, 3};
1335 \\
1336 \\ __v8hi a = {0, 1, 2, 3, 4, 5, 6, 7};
1337 \\ __v8hi b = (__v8hi) {100, 200, 300, 400, 500, 600, 700, 800};
1338 \\
1339 \\ __v8hi sum = a + b;
1340 \\ for (int i = 0; i < 8; i++) {
1341 \\ if (sum[i] != a[i] + b[i]) abort();
1342 \\ }
1343 \\ return 0;
1344 \\}
1345 , "");
1346 }
1325 cases.add("basic vector expressions",
1326 \\#include <stdlib.h>
1327 \\#include <stdint.h>
1328 \\typedef int16_t __v8hi __attribute__((__vector_size__(16)));
1329 \\int main(int argc, char**argv) {
1330 \\ __v8hi uninitialized;
1331 \\ __v8hi empty_init = {};
1332 \\ for (int i = 0; i < 8; i++) {
1333 \\ if (empty_init[i] != 0) abort();
1334 \\ }
1335 \\ __v8hi partial_init = {0, 1, 2, 3};
1336 \\
1337 \\ __v8hi a = {0, 1, 2, 3, 4, 5, 6, 7};
1338 \\ __v8hi b = (__v8hi) {100, 200, 300, 400, 500, 600, 700, 800};
1339 \\
1340 \\ __v8hi sum = a + b;
1341 \\ for (int i = 0; i < 8; i++) {
1342 \\ if (sum[i] != a[i] + b[i]) abort();
1343 \\ }
1344 \\ return 0;
1345 \\}
1346 , "");
13471347
13481348 cases.add("__builtin_shufflevector",
13491349 \\#include <stdlib.h>
tools/update_cpu_features.zig+1-1
......@@ -793,7 +793,7 @@ const llvm_targets = [_]LlvmTarget{
793793 .td_name = "Sparc.td",
794794 },
795795 .{
796 .zig_name = "systemz",
796 .zig_name = "s390x",
797797 .llvm_name = "SystemZ",
798798 .td_name = "SystemZ.td",
799799 },